static class DynamicSumExtensions
{
public static T DynamicSum<T>(this IEnumerable<T> source)
{
dynamic total = default(T);//即将使用的动态类型
//total 0 用default(T)来初始化total,它声明为dynamic,因此可以得到所需的动态行为
//这样我们必须以某种方式使用一个初始值来开始操作;也可以使用序列中的第一个值,
//但如果序列没有元素就无法继续进行了。对于不可空的值类型,default(T)几乎总是一个
//恰当的值:即自然数0。对于引用类型,我们会将序列中的第一个元素与null相加,这
//可能是恰当的,也可能不恰当的。对于可空值类型,最终会将第一个元素与该类型的空值
//相加,这肯定是不恰当的。
foreach (T element in source)
//element 1 2 3
{
total = (T) (total + element);//动态地选择其他操作符
//total 1 3 6
}
return total;
}
}
class DynamicSum
{
static void Main()//弥补泛型操作符的不足 动态地对任意元素的序列进行求和
{
byte[] bytes = new byte[] { 1, 2, 3 };
//bytes {byte[3]}
Console.WriteLine(bytes.DynamicSum());//输出6
}
}
Enumerable.Sum的重载方法列表呢?它相对长,其中的一半用于投影,但即使这样重载也有
10个之多,每个重载都只是获取一个元素序列,并将它们相加。而且这还不包括对无符号值、
byte和short进行求和。可以用动态类型将它们放到一个方法里。
内部使用动态类型,方法是静态类型的。可以将其声明一个对IEnumerable<dynamic>求和
的非泛型方法,但由于协变性的限制,这样并不能很好地工作。将方法名称由Sum改为DynamicSum,
以避免与Enumerable中的方法冲突。因为如果两个方法的签名包含的参数类型相同,编译器将
选择非泛型重载,而不是泛型重载,而更改方法名称可以简单地在一开始就避免这种冲突。
输出
6