【问题标题】:Why can I not compare two generic objects of a certain implicit type?为什么我不能比较某个隐式类型的两个泛型对象?
【发布时间】:2009-10-16 17:48:54
【问题描述】:

考虑以下代码:

public class SystemManager<T> where T : ISettings
{
    public SystemManager()
    {
        T implicit1 = default(T);
        T implicit2 = default(T);
        if (implicit1 != implicit2)
        {
            // This will not compile saying the compiler cannot compare
            // using '!=' two objects of type 'T' and 'T'
        }

        ISettings explicit1 = null;
        ISettings explicit2 = null;
        if (explicit1 != explicit2)
        {
            // This will compile fine
        }
    }
}

在上面,编译器知道 T ISettings,那么为什么比较只在泛型范围之外起作用呢?这会成为“.NET 4 就是答案”的事情之一吗?

编辑:

在回答 Manu 的问题时,为什么直接使用泛型而不是 ISettings。

假设如下:

void Main()
{
    SystemManager<XmlSettings> manager = new SystemManager<XmlSettings>();
    // I want to disallow the following
    SystemManager<RegistrySettings> manager = new SystemManager<RegistrySettings>();
}

public interface ISettings
{

}

public class XmlSettings : ISettings, IDisposable
{
    public void Dispose() {  }
}

public class RegistrySettings : ISettings
{
}

这样,我不允许任何不实现 IDisposable 的 ISettings 实现。例如,我无法控制 ISettings,也无法让其他类实现 ISettingsDisposable 类。

Disposable 显然是一个例子,但您可以在其中放置任何东西 - 我可能想要限制比 ISettings 更严格的想法。

编辑 2:

针对关于结构不具备 == 能力的观点:

public struct StructSettings : ISettings
{

}

我可以执行上述操作并实现一个通用的 StructSettings 版本的 SystemManager:

然后,在 SystemManager 中,我可以比较这两个结构而不会出现运行时错误。

SystemManager<StructSettings> manager = new SystemManager<StructSettings>();

这可行,并且 SystemManager 的构造函数中结构上的 == 不会引发任何运行时错误。

【问题讨论】:

  • 我没有答案,但是当您可以直接使用类型 ISettings 时,为什么需要使用泛型?
  • @Manu - 我更新了我的问题,回答了您的问题

标签: .net generics


【解决方案1】:

有趣:我认为这与编译器不知道 T 是引用还是值类型有关,因为如果添加约束 T : class- 它编译就好了。

比较的语义是比较引用是否相等。

【讨论】:

  • @Vitality - 查看我更新的答案(编辑 2)。如果 ISettings 是 ref 或 value 类型,它肯定不知道显式版本吗?
  • 我不确定你做了什么。如果你不设置类约束,这个东西不会编译。我不明白你是如何编译它的?
【解决方案2】:

显然运算符 == 没有在结构中实现。这就是为什么如果你把 T : class ,它会工作。


文件的链接,这样我们就可以看到你说的工作版本会很棒:)。或者只是编辑您的帖子。

【讨论】:

  • 但是我在显式示例中的 ISettings 实现可能是一个 Struct,这让我感到困惑
  • 那么你需要 ISettings 来实现 IEquatable,因为 Struct 上没有默认 ==。
  • @sirrocco - 我已经更新了我的问题,对你的回答提出了一点看法
  • 如果您使用的是第二个版本“ISettings explicit1 = null;” - 那么explicit1 是一个引用类型,这就是它起作用的原因。只需实现 IEquatable 使用 .Equals 并完成它:)
  • @sirrocco - 我可以让这一切都正常工作 - 与 null 进行比较,然后使用 .Equals 进行检查(否则 .Equals 显然会在 null 上失败) - 但我想知道发生了什么编译器的头! :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-13
  • 2012-12-06
  • 1970-01-01
  • 2012-05-11
  • 1970-01-01
  • 1970-01-01
  • 2017-08-04
相关资源
最近更新 更多