使用扩展方法来构建一个坏主意?

时间:2013-05-29 17:53:35

标签: c# casting

我最近开始使用WPF,我注意到你必须进行大量的转换(特别是对于事件)。这是一个美学问题,但我想知道如果我使用扩展方法进行投射而不是使用普通投射会有多糟糕。

public static T Cast<T>(this object obj)
{
    return (T)obj;
}

这意味着我可以阻止一些嵌套的parantheses,并改变:

Console.WriteLine(((DataGridCell)e.OriginalSource).ActualHeight);

为:

Console.WriteLine(e.OriginalSource.Cast<DataGridCell>().ActualHeight);

我可能会忽略任何明显的缺点吗?人们在代码中遇到这种情况时会有多厌恶? :)

2 个答案:

答案 0 :(得分:17)

这与Enumerable.Cast的意图相似,所以我不一定会说人们会反感。

  

我可能会忽略任何明显的缺点吗?

主要的缺点是,这将是代码中每个变量的扩展方法,因为您正在扩展System.Object。出于这个原因,我通常会在Object上避免使用扩展方法,因为它会“污染”智能感知。

话虽如此,还有其他缺点:

如果您在现有IEnumerable上使用此功能,则会与Enumerable.Cast<T>发生名称冲突。包含您的命名空间但缺少using System.Linq的文件很容易被其他开发人员误解,因为这与预期的“Cast<T>”扩展方法有着截然不同的含义。

如果在值类型上使用它,则引入装箱(将值类型推送到对象中),然后是unbox和cast,这实际上可能导致转换不会发生的异常。如果您这样做,您的扩展方法将引发异常:

int i = 42; 
float f = i.Cast<float>();

这可能是意料之外的,因为float f = (float)i;完全合法。有关详细信息,请参阅Eric Lippert在Representation and Identity上的帖子。如果您这样写,我肯定会建议您向运营商添加class constraint

我个人只会使用括号。这是一种常用的语言支持功能,对于所有C#开发人员来说都应该是可以理解的。铸造具有更短,易懂和无副作用(在智能感等方面)的优点。

另一种选择是使这成为一个普通的静态方法,它允许你写:

Console.WriteLine(Utilities.Cast<DataGridCell>(e.OriginalSource).ActualHeight);

这消除了“污染”智能感知的缺点,并且很明显它是你编写的方法,但增加了使用所需的输入量。它也没有阻止拳击和unbox / cast问题。

答案 1 :(得分:6)

主要的缺点是每个C#开发人员都知道强制转换,而你的Cast<T>方法只是另一个未发明的方法。下一步通常是一组扩展程序,例如IsTrueIsFalseIsNull等。

这是一种语法垃圾。