【问题标题】:Should Contravariance Allow the Compiler to Infer T=Circle?逆变应该允许编译器推断 T=Circle 吗?
【发布时间】:2012-08-09 16:46:18
【问题描述】:

好的,我被告知,由于逆变性,编译器应该能够推断出 T=Circle 并因此允许编译。但是,使用编译器版本 4.0.30319.1 我收到以下错误:

错误 CS0311:类型“Testable.Shape”不能用作泛型类型或方法“Testable.Test.Foo(System.IComparable, T)”中的类型参数“T”。没有从“Testable.Shape”到“Testable.ICircle”的隐式引用转换。

但是,如果我在 Circle 类上实现 IComparable,则代码可以正常编译。这里可能有什么问题?

using System; 

namespace Testable 
{ 
    public class Test 
    { 
        public static void Main() 
        { 
            Foo(new Circle(), new Circle()); 
        } 

        public static void Foo<T>(IComparable<T> a, T b) where T : ICircle 
        { 
            a.CompareTo(b); 
        } 
    } 

    public interface ICircle 
    { 
    } 

    public class Shape : IComparable<Shape>
    { 
        public Int32 CompareTo(Shape other) 
        { 
            Console.WriteLine("Called CompareTo(Shape)"); 
            return 0; 
        } 
    } 

    public class Circle : Shape, ICircle 
    { 
    } 
}

【问题讨论】:

    标签: c# contravariance compareto


    【解决方案1】:

    问题在于Circle 实现了IComparable&lt;Shape&gt;,因此编译器为T 选择了Shape。但是,Shape 没有实现ICircle,因此您会看到您看到的错误。

    不过,我想这引出了问题。为什么编译器在看到ICircle 约束后不将其猜测修改为Circle。答案是constraints are not used to aid in type inference。他们只能在猜测完成后使无效。

    【讨论】:

    • 感谢您的参考,今晚晚些时候我一定会阅读它。(考试和所有)
    • 假设 Circle 是在另一个命名空间中定义的。鉴于以后可以在其他命名空间中添加新类,编译器将无法在 Foo 的调用站点“修改其猜测”。 “最佳猜测”在编译时可能不可用。我们可以通过指定类型参数来给编译器一个提示:Foo&lt;Circle&gt;(new Circle(), new Circle())
    猜你喜欢
    • 2011-06-21
    • 2019-04-21
    • 1970-01-01
    • 2011-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-23
    相关资源
    最近更新 更多