通常检查null,不会在非约束类型上包含nullables。
假设我有以下方法:
public static int CountNonNullMembers(this IEnumerable enumerable) { if (enumerable == null) throw new ArgumentNullException("enumerable"); int count = 0; foreach (var x in enumerable) { if (x != null) count++; } return count; }
我有这3个arrays::
var ints = Enumerable.Range(0,10).ToArray(); var nullableInts = Array.ConvertAll(ints,x=>x as int?); var strings = Array.ConvertAll(ints,x => x.ToString());
我写了一个小函数来做一个循环并计算一百万次迭代。 将它应用于ints
和strings
,它在我的机器上完成大约100毫秒。 对于nullableInts
,需要2.5秒。 据我所知,在int
上检查null是没有意义的,因此编译器为不可为空的struct
类型提供了不同的模板,这将删除空检查。 但是Nullable
没有将空检查转换为x.HasValue
的模板。 如果我有一个无约束的函数,我怎么能做一个表现良好的空检查? 我不能使用EqualityComparer
,因为null可能不是T
的成员,因为没有约束。
也不可能有因约束而不同的重载,所以我不能说,有一个用于structs
,一个用于Nullable
,一个用于类。
该方法的调用者是非约束的。 这只是一个例子(不是实际的方法); 调用方法是非约束的。 我需要针对非null成员做一些工作,这是一种通用方法。 我想我可以编写一个不执行检查的版本与执行该版本的版本(因此具有不同的签名),但它看起来非常难看且不需要。
此外,扩展方法.Count
莫名其妙地对NullableInts
和strings
执行可怕(同样糟糕),所以它真的不是正确的方法。 这可能是委托调用,但我对此表示怀疑。 使用Check.IfNull
的UnboxT
样式方法Check.IfNull
执行得更好。 好吧,真的很奇怪切换计数的主体到这个表现很好:
public static int CountNonNullMembers(this IEnumerable enumerable) { return enumerable.Count(Check.IfNull.Invoke); }
为什么?
您可以将generics类型参数约束为引用类型或值类型:
public static int CountNonNull(this IEnumerable source) where T : class { return source.Count(x => x != null); } public static int CountNonNull (this IEnumerable> source) where T : struct { return source.Count(x => x.HasValue); }
对于不可为空的结构,您不需要重载,因为它们无论如何都不能为空。
使用UnboxT
方法有效。 但我也想要一些不需要创建静态类型的东西::
public static class Check { public static readonly Predicate IfNull = CreateIfNullDelegate(); private static bool AlwaysFalse(T obj) { return false; } private static bool ForRefType(T obj) { return object.ReferenceEquals(obj, null); } private static bool ForNullable(Tu? obj) where Tu:struct { return !obj.HasValue; } private static Predicate CreateIfNullDelegate() { if (!typeof(T).IsValueType) return ForRefType; else { Type underlying; if ((underlying = Nullable.GetUnderlyingType(typeof(T))) != null) { return Delegate.CreateDelegate( typeof(Predicate ), typeof(Check ) .GetMethod("ForNullable",BindingFlags.NonPublic | BindingFlags.Static) .MakeGenericMethod(underlying) ) as Predicate ; } else { return AlwaysFalse; } } } }
使用这种方法,一切都表现相同。 Strings
表现更差,但并不比其他任何东西差。
虽然不一定比你的方法更好,但它不需要整个类:
上述就是C#学习教程:通常检查null,不会在非约束类型上包含nullables。分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
static Dictionary NullChecks = new Dictionary(); public static Func MakeNullCheck() { object obj; Func func; if (NullChecks.TryGetValue(typeof(T), out obj)) return (Func)obj; if (typeof(T).IsClass) func = x => x != null; else if (Nullable.GetUnderlyingType(typeof(T)) != null) { var param = Expression.Parameter(typeof(T)); func = Expression.Lambda>( Expression.Property(param, typeof(T).GetProperty("HasValue")), param).Compile(); } else func = x => false; NullChecks[typeof(T)] = func; return func; }
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/949092.html