假设我有以下方法:
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
and strings
,在我的机器上大约需要 100 毫秒即可完成。为了nullableInts
,需要2.5秒。
据我了解,检查空值int
没有意义,因此编译器对于不可为空有不同的模板struct
类型,删除空检查。但Nullable<T>
没有将空检查转换为的模板x.HasValue
。如果我有一个不受约束的函数,如何进行空检查以使其性能良好?我不能使用EqualityComparer<T>
,因为 null 可能不是以下成员T
因为没有任何限制。
而且不可能有因约束而异的重载,所以我不能,比如说,有一个structs
, 一个用于Nullable<T>
,还有一个用于课程。
该方法的调用者是不受约束的。这只是一个示例(不是实际方法);方法调用是不受约束的。我需要对非空成员做一些工作,这是一个通用方法。我想我可以编写一个不进行检查的版本与进行检查的版本(因此具有不同的签名),但它看起来非常丑陋且不需要。
另外,扩展方法.Count
莫名其妙地表现得很糟糕NullableInts
and strings
,(同样糟糕),所以这确实不是正确的方法。这可能是委托调用,但我对此表示怀疑。使用UnboxT
风格方法Check<T>.IfNull
表现好多了。
好吧,真的很奇怪,将计数主体切换到这个效果很好:
public static int CountNonNullMembers<T>(this IEnumerable<T> enumerable)
{
return enumerable.Count(Check<T>.IfNull.Invoke);
}
Why?