假设我有以下方法:
public static int CountNonNullMembers<T>(this IEnumerable<T> enumerable)
{
if (enumerable == null) throw new ArgumentNullException("enumerable");
int count = 0;
foreach (var x in enumerable)
{
if (x != null) count++;
}
return count;
}
我有这 3 个数组::
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
是否为空没有意义,所以编译器有一个不同的非空模板 struct
类型,删除空检查。但是Nullable<T>
没有将空检查转换为 x.HasValue
的模板.如果我有一个不受约束的函数,我怎样才能进行性能良好的空值检查?我不能使用 EqualityComparer<T>
,因为 null 可能不是 T
的成员因为没有约束。
此外,不可能有因约束而异的重载,所以我不能,比如说,为 structs
设置一个重载。 , 一个用于 Nullable<T>
,还有一个用于类(class)。
方法的调用者是不受约束的。这只是一个例子(不是实际的方法);方法调用是不受约束的。我需要对非空成员做一些工作,这是一种通用方法。我想我可以编写一个不进行检查的版本与一个进行检查的版本(因此具有不同的签名),但它看起来非常丑陋且不需要。
另外,扩展方法.Count
莫名其妙地为 NullableInts
表现得很糟糕和 strings
,(同样糟糕),所以这确实不是正确的方法。这可能是委托(delegate)调用,但我对此表示怀疑。使用 UnboxT
Check<T>.IfNull
的样式方法表现好多了。
好吧,真的很奇怪,将 count 的主体切换到这个执行得很好:
public static int CountNonNullMembers<T>(this IEnumerable<T> enumerable)
{
return enumerable.Count(Check<T>.IfNull.Invoke);
}
为什么?
最佳答案
您可以 constrain generic type parameters引用类型或值类型:
public static int CountNonNull<T>(this IEnumerable<T> source)
where T : class
{
return source.Count(x => x != null);
}
public static int CountNonNull<T>(this IEnumerable<Nullable<T>> source)
where T : struct
{
return source.Count(x => x.HasValue);
}
对于不可为 null 的结构不需要重载,因为它们无论如何都不能为 null。
关于c# - 一般检查不会在非约束类型上装箱可空值的 null。,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3999761/