当前位置: 首页 > 编程语言 > C#

Sharing

时间:2023-04-10 20:40:32 C#

genericsandNullableTypes泛型和可空类型假设我有一个方法将一个int作为一个字符串,如果解析成功则返回一个int,否则返回一个null值。诠释?ParseValue(stringintAsString){inti;如果(int.TryParse(intAsString,outi))返回i;返回空值;}如何重写此方法,使其不仅适用于整数?,你也可以使用long?,decimal?和日期时间??你应该提到这很有趣,因为前几天我在搞这样的事情:usingSystem;使用System.Reflection;staticclassExample{publicstaticTupleTryParse(thisStringcandidate)whereT:struct{T?值=空;布尔成功=假;varparser=ParsingBinder.GetParser();尝试{值=解析器(候选人);成功=真;}catch(FormatException){}returnnewTuple(success,value);}}静态类ParsingBinder{静态Func解析器;publicstaticFuncGetParser(){if(parser==null)parser=getParser();返回解析器;}staticFuncgetParser(){MethodInfomethodInfo=typeof(T).GetMethod("Parse",new[]{typeof(String)});if(methodInfo==null)thrownewException("无法检索类型的"Parse"方法。");返回(Func)Delegate.CreateDelegate(typeof(Func),methodInfo);这是一个类似的方法,但可以将其视为像一个更好的TryParse方法,它返回一个元组(这需要.NET4)元组的第一个属性是一个布尔值,指示解析尝试的成功或失败,第二个属性是泛型类型的可选参数一个空值,如果解析失败则为null,如果解析成功则为null。它通过使用反射从泛型类型参数中检索静态Parse(String)方法并为传入的字符串调用该方法来工作。我将其构建为扩展方法,以允许您执行以下操作:varintValue="1234".TryParse();vardoubleValue="1234".TryParse();不幸的是,这对枚举不起作用,因为它们没有相同的解析方法签名,所以你不能使用这个扩展来解析枚举,但不难破解它来做一个特殊的案例。枚举。这种方法的一个Parse是,通过反射检索Parse方法的成本仅在第一次使用时发生,因为为所有后续使用创建了静态委托。还有一件事-这种方法唯一笨拙的地方是没有语言扩展或语法糖来使其易于使用。我希望通过这段代码实现的是一种使用BCL中存在的标准TryParse方法的不那么笨拙的方法。我个人觉得这个模式很难看:Int32值;if(Int32.TryParse(someString,outvalue))//对value做一些事情主要是因为它需要提前声明变量并使用out参数。我上面的方法效果不佳:varresult=someString.TryParse();if(result.Item1)//dosomethingwithresult.Item2看到使用Tuple的C#语言扩展真的很酷,它使我们能够顺利地使用这种类型,但我觉得我写的越多越好似乎不可行。您可以显式使用Nullable关键字而不是问号:例如,int?equalsNullable因此将原始设计切换为NullableParseValue(stringvalueAsString)应该可以解决问题:之后执行通用实现。最好实现扩展方法,它甚至可以解析枚举。这样你就可以像这样得到一个Nullable:publicstaticT?Parse(thisstringtext)whereT:struct{objecto=null;}尝试{varttype=typeof(T);如果(ttype.IsEnum){Tn=默认(T);if(Enum.TryParse(text,true,outn))返回n;}否则o=转换。更改类型(文本,ttype);}catch{}if(o==null)returnnewNullable();返回新的Nullable((T)o);如果你能等到C#4.0,你可以使用dynamic关键字来解决这类问题。不太明白安卓的方案为什么要用Tuple,反正我们只要返回Nullable就好了,好像是把同样的事情做了两次。我编辑了他的解决方案以使用TryParse并允许返回Nullable或指定为参数的默认值。//////////////////publicstaticNullableTryParse(thisstringaText)whereT:struct{Tvalue;if(ParsingBinder.TryParse(aText,outvalue)){返回值;}返回空值;}/////////////////////publicstaticTTryParse(thisstringaText,TaDefault)whereT:struct{Tvalue;if(!ParsingBinder.TryParse(aText,outvalue)){value=aDefault;}返回值;}////////////staticclassParsingBinderwhereT:struct{/////////////////////publicdelegateboolDelegate_TryParse(stringaText,outTaOutput)whereT:struct;/////////staticDelegate_TryParsemethodTryParse;////////////publicstaticDelegate_TryParseTryParse{get{if(methodTryParse==null){methodTryParse=GetParserMethod();}}返回方法TryParse;}}////////////staticDelegate_TryParseGetParserMethod(){vartypeT=typeof(T);varparamTypes=newType[]{typeof(string),typeT.MakeByRefType()};变我thodInfo=typeT.GetMethod("TryParse",BindingFlags.Static|BindingFlags.Public,null,paramTypes,null);if(methodInfo==null){varmessage=String.Format("无法为类型'{0}'检索'TryParse'方法。",typeT.Name);抛出新的异常(消息);}return(Delegate_TryParse)Delegate.CreateDelegate(typeof(Delegate_TryParse),methodInfo);你实际上可以更新Matt的代码所说的做了和做的,这里是代码:在这里输入代码:staticT?TryParse(stringparse)whereT:struct{类型t=typeof(T);如果(t==typeof(int)){inti;如果(int.TryParse(parse,outi))return(T)(object)i;返回空值;//Console.WriteLine(t.Name);}if(t==typeof(double)){doublei;如果(double.TryParse(parse,outi))return(T)(object)i;返回空值;}//blabla,更多的逻辑如datetime等数据类型返回null;并且,你可以像这样使用它:double?我=TryParse("111.111");诠释?a=TryParse("111");您列出的类型都有一个名为TryParse的静态方法它们看起来很相似,但实际上具有完全不同的签名。它们遵循相似的“模式”,但编译器无法检测到。你可能会尝试这样的事情:publicT?ParseValue(stringvalue)whereT:struct{if(typeof(T)==typeof(int)){inti;如果(int.TryParse(value,outi))返回(T)(object)i;返回空值;}if(typeof(T)==typeof(decimal)){decimald;if(decimal.TryParse(value,outd))return(T)(object)d;返回空值;}//其他支持的类型...thrownewArgumentException("Typenotsupported");但是,你不能。编译器无法知道(在编译时)如何将类型“T”转换为int(或任何其他类型)。您可以使用双重转换来完成这项工作。(感谢Dotson)用法:以上就是C#学习教程分享的全部内容:泛型和可空类型。如果对大家有用,需要进一步了解C#学习教程,希望大家多多关注——varmydecimal=ParseValue("12.1");varmyint=ParseValue("-22");varbadint=ParseValue("坏");//badint.HasValue==false本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理会员删除。如需转载请注明出处: