14

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

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

这意味着我可以防止一些嵌套的括号,并更改:

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

至:

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

有没有我可能忽略的明显缺点?人们在代码中遇到这种情况会有多反感?:)

4

2 回答 2

17

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

有没有我可能忽略的明显缺点?

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

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

如果您在现有的. 上使用它IEnumerable,则会与Enumerable.Cast<T>. 包含您的命名空间但缺少 a 的文件using System.Linq很容易被其他开发人员误解,因为这与预期的 " Cast<T>" 扩展方法具有非常不同的含义。

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

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

这可能是出乎意料的,因为这float f = (float)i;是完全合法的。有关详细信息,请参阅 Eric Lippert 关于表示和身份的帖子。如果你写这个,我肯定会推荐给你的操作符添加一个类约束

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

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

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

这消除了“污染”智能感知的缺点,并使其明显是您编写的方法,但增加了使用所需的输入量。它也无助于防止装箱和拆箱/投射问题。

于 2013-05-29T17:56:05.960 回答
6

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

这是一个语法垃圾。

于 2013-05-29T17:57:26.760 回答