为什么我不能比较某个隐式类型的两个通用对象?

时间:2009-10-16 08:20:27

标签: .net generics

请考虑以下代码:

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
{

}

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

然后,在SystemManager中,我可以比较两个结构,没有运行时错误。

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

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

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:2)

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


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