【问题标题】:C# generic constraints : InterfaceC# 泛型约束:接口
【发布时间】:2014-07-02 11:18:43
【问题描述】:

我对一些代码有疑问:

interface IDistance<T> 
{
        double distance();
        double distance(T obj);
}

class Point<T> where T : IDistance<T>  //why do i need this?
{
        T obj;
        public double dist(T val) { return obj.distance(val); 
        public Point(T obj) { this.obj = obj; }
}

class P2D : IDistance<P2D>
{
        public double[] x = new double[2];

        public P2D(double x, double y)
        {
            this.x[0] = x; this.x[1] = y;
        }

        public double distance()
        {
            double d = 0.0;
            for (int i = 0; i < 2; i++) d = d + x[i] * x[i];
            return Math.Sqrt(d);
        }

        public double distance(P2D val)
        {
           double d = 0.0;
           for (int i = 0; i < 2; i++) d = d + Math.Pow(x[i]-val.x[i],2);
           return Math.Sqrt(d);
        }
}

class Tester
{
        static void Main(string[] args)
        {
            P2D P1 = new P2D(3.0, 4.0);
            Point<P2D> C1 = new Point<P2D>(P1);
            Console.WriteLine(C1.dist());
        }
} 

详细的代码并不重要。

为什么在泛型类Point&lt;T&gt; 中需要约束where T : IDistance&lt;T&gt;

当我只指定已经实现接口IDistance&lt;T&gt; 的类时 P2D类,不应该是Point类中已经隐式实现的接口吗?

我知道它可能会导致问题,当在类Point 中定义一个类型为&lt;T&gt; 的类时,它还没有实现接口。但是在这种情况下,为什么不可能呢?

【问题讨论】:

    标签: c# generics interface where


    【解决方案1】:

    Point&lt;T&gt;内的这段代码:

    T obj;
    public double dist(T val) { return obj.distance(val); 
    

    当编译器试图理解这个表达式的含义时:

    obj.distance(val)
    

    它必须解析distance 成员。如果T 不受约束,则不能这样做。当T 被限制为实现IDistance&lt;T&gt; 时,它可以 - 将其解析为接口的成员。

    特别是,如果没有约束,我可以以非常奇怪的方式使用该类型:

    Point<string> weird = new Point<string>("foo");
    double result = weird.dist("bar");
    

    你希望它做什么?

    (附带说明,即使是示例,也值得遵循正常的 .NET 命名约定。方法应该是 PascalCased,我永远不会调用类 P2D...)

    【讨论】:

      【解决方案2】:

      当我只指定已经实现接口 IDistance 的类(如 Class P2D)时,不应该是已经在 Class Point 中隐式实现的接口吗?我知道它可能会导致问题,当在 Class Point 中定义了一个没有实现接口的类作为类型时。但是在这种情况下,为什么不可能呢?

      因为 C# 是一种具有编译时类型安全性的语言。如果没有该约束,您可能只能在运行时使用 T 的值实例化 Point&lt;T&gt;,它实现 IDistance&lt;T&gt;,但是编译器无法在编译时知道您会表现得如此好。

      【讨论】:

        【解决方案3】:

        我为什么需要这个?

        您需要约束,因为您将泛型类型限制为接口IDistance&lt;T&gt; 的实现。如果Point 类你使用这种类型的一些方法,比如obj.distance(val);

        您还可以使用抽象类来限制派生。查看 MSDN 中的文档。 http://msdn.microsoft.com/en-us/library/bb384067.aspx

        【讨论】:

          【解决方案4】:
          class Point<T> where T : IDistance<T>  //why do i need this?
          

          你需要这个,因为你声明的类,应该将一个实现名为IDistance&lt;T&gt;的接口的类型作为类型

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-04-21
            • 2010-11-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多