我对一些代码提出了一个问题:
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());
}
}
详细的代码并不重要。
为什么我需要通用类where T : IDistance<T>
中的约束Point<T>
?
当我只指定已实现接口IDistance<T>
的类时
P2D类不应该是类Point
中隐含的已经实现的接口吗?
我认为当类<T>
中的类Point
定义为未实现接口时,它可能会导致问题。但在这种情况下,为什么不可能呢?
答案 0 :(得分:2)
在Point<T>
中查看此代码:
T obj;
public double dist(T val) { return obj.distance(val);
当编译器试图理解这个表达式的含义时:
obj.distance(val)
必须解析distance
成员。如果T
不受约束,则不能这样做。当T
被限制为实现IDistance<T>
时,它可以 - 它将其解析为接口的成员。
特别是,没有约束,我可以用很奇怪的方式使用这个类型:
Point<string> weird = new Point<string>("foo");
double result = weird.dist("bar");
你期望做什么?
(作为旁注,值得遵循正常的.NET命名约定,即使是示例。方法应该是PascalCased,我永远不会调用类P2D
...)
答案 1 :(得分:1)
为什么我需要这个?
您需要约束,因为您将通用类型限制为接口IDistance<T>
的实现。如果Point
类使用此类型的某些方法,例如obj.distance(val);
。
您还可以使用抽象类来限制派生。看看MSDN中的文档。 http://msdn.microsoft.com/en-us/library/bb384067.aspx
答案 2 :(得分:1)
当我只指定已经实现了类P2D之类的接口IDistance的类时,不应该是已经在Class Point中隐式实现的接口吗?当定义类Point中的类没有实现接口时,我会发现它可能导致问题。但在这种情况下,为什么不可能呢?
因为C#是一种具有编译时类型安全性的语言。如果没有该约束,您可能只在运行时使用Point<T>
实例化T
来实现IDistance<T>
,但编译器无法在编译时知道您将如此乖巧。
答案 3 :(得分:0)
class Point<T> where T : IDistance<T> //why do i need this?
你需要这个,因为你声明的类应该是一个实现名为IDistance<T>
的接口的类型