【问题标题】:Why cant you require operator overloading in generics [closed]为什么不能在泛型中要求运算符重载[关闭]
【发布时间】:2013-01-15 18:02:35
【问题描述】:

在 C++ 中,您可以编写如下代码:

template<class T>
T Add(T lhs, T rhs)
{
    return lhs + rhs;
}

但是,你不能在 C# 中做这样的事情:

public static T Add<T>(T x, T y) where T : operator+
{
    return x + y;
}

有什么原因吗?我知道它可以通过反射来完成(通用Add 带有对象,然后对它进行类型检查),但这效率低下并且不能很好地扩展。那么,为什么?

【问题讨论】:

  • 这看起来像 stackoverflow.com/questions/756954/… 的副本
  • @neontapir 接受的答案使用反射。我提到我知道可以这样做,但我不想这样做。
  • 我认为在第二段中您的意思是您不能在 C# 中执行此操作,即问题是“为什么没有运算符重载类型约束?” (顺便说一句,我不知道答案)。
  • c++ 泛型与 c# 模板不同,并且没有相同的行为。 “为什么”不是堆栈溢出的好问题。

标签: c# .net generics cil cil-metadata


【解决方案1】:

没有内在的原因这不可能存在。实现泛型类型约束的方式是通过接口调用。如果有一个提供operator+ 的接口,这将起作用。

所有相关类型都需要此接口,但要与基于 C++ 模板的类比一样通用。

另一个问题是 .NET 没有多重分派。接口调用将是不对称的:a.Plus(b) 可能意味着与b.Plus(a) 不同的东西。 Equals 有同样的问题,顺便说一句。

所以这个问题可能不符合“有用”栏或“成本/效用”栏。这不是不可能的问题,而是实际问题。

证明这是可能的:((dynamic)a) + ((dynamic)b)

【讨论】:

  • 一件事你没有提到(至少没有明确地):不可能有一个接口提供operator+,因为运营商必须是static方法和static 方法不能是接口的成员。
  • @svick 我说的是 .NET 的假设未来版本。可以使用实例方法版本来增强运算符。现在,你是对的。
【解决方案2】:

CLR 本身并不支持此类约束,C# 设计团队显然决定支持与 CLR 相同的一组约束。大概 CLR 团队和 C# 团队都认为实现这样一个特性的好处并没有超过规范、实现和测试它的成本。

如果您想使用支持此类约束的 .NET 语言,请考虑查看 F#。

【讨论】:

  • 虽然我相信 F# 仅在某些情况下支持此类约束(因为 CLR 约束的限制)。
  • @svick - F# 在可能的情况下使用 CLR 约束,但有自己的元数据格式来表示大量无法在 CLR 类型系统中表达的 F# 特定信息。其中一项是成员约束,它要求类型具有具有特定名称和签名的方法。
【解决方案3】:

有几种可能的方法来实现运算符约束,所有这些方法要么不重要(并且可能需要更改 CLR),要么具有明显的缺点(例如,它们会很慢,比添加两个整数要慢得多) .

这是一个相对容易解决的问题(使用 dynamic 的缓慢、通用和不安全的方式,或者具有 bajillion 重载的快速、特定类型和安全的方式)。因此,此类功能可能被认为是“值得拥有”,但远不足以保证进行此类更改。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-13
    • 2017-04-28
    • 2013-07-30
    • 1970-01-01
    • 1970-01-01
    • 2013-10-14
    • 1970-01-01
    相关资源
    最近更新 更多