2014-07-02 60 views
1

我得到了一些代碼的一個問題:C#泛型約束:接口

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<T>中的約束where T : IDistance<T>

當我只指定一個已經實現的接口IDistance<T>像 類P2D班,不應接口已經在類Point實現隱?

我得到這樣一個事實,即它可能會導致問題,當類<T>中的類Point被定義爲未實現該接口時。但在這種情況下,爲什麼不可能?

回答

2

看看這段代碼的接口類型:

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

爲什麼我需要這個?

您需要約束,因爲您將通用類型限制爲接口的實現IDistance<T>。如果Point類使用了這種類型的一些方法,如obj.distance(val);

您也可以使用抽象類來限制派生。看看MSDN中的文檔。 http://msdn.microsoft.com/en-us/library/bb384067.aspx

0
class Point<T> where T : IDistance<T> //why do i need this? 

你需要這個監守你聲明類,應在Point<T>採取類型實現所謂IDistance<T>

1

當我只指定已經實現類ID P2D的接口IDistance的類,不應該是已經實現的在Class Point中隱含的接口?當Class類中的類被定義爲未實現接口時,我得到它可能導致問題的事實。但在這種情況下,爲什麼不可能?

因爲C#是一種具有編譯時類型安全性的語言。沒有這個限制,你只能在運行時實例化Point<T>,其值爲T,它實現IDistance<T>,但編譯器在編譯時沒有辦法知道你會如此行事。