2016-01-18 22 views
4

現在我們有兩個結構來表示2d點。泛型或多個類

public struct Point2D 
{ 
    public double X { get; set; } 
    public double Y { get; set; } 
} 

public struct Point2DF 
{ 
    public float X { get; set; } 
    public float Y { get; set; } 
} 

現在我們需要製造另一個結構來表示二維點的整數。

public struct Point2DI 
{ 
    public int X { get; set; } 
    public int Y { get; set; } 
} 

我的問題是我應該在這裏使用泛型?如果我使用泛型,我將有一個結構而不是三個。

public struct Point<T> 
{ 
    public T X { get; set; } 
    public T Y { get; set; } 
} 

但是消費者可以將T設置爲字符串或某些類/結構。我該怎麼辦?有什麼辦法可以強制T是雙/ int/float?

+3

泛型不會以任何方式幫助你。你最好創建多種類型。 –

+0

正如在其他問題中所解釋的那樣,您不能對C#中的數字類型進行約束。這是不可能的。你要麼必須忍受那種(也許增加運行時類型檢查),要麼堅持使用單獨的類型。 – poke

+1

C#*沒有'Numeric'類(像* Java *那樣),所以,唉,泛型不會有幫助。 –

回答

3

你不能爲數字類型創建約束,你最多隻能做到最接近的是:

public struct Point<T> where T:struct, IComparable 

爲所有數值類型實現IComparable和所有的基本類型有struct小號


UPDATE

此外,您可以修改您的架構,只需創建Point個S作爲如下

public abstract class Point 
{ 
    protected Point() 
    { 

    } 

    public static Point Create<T>(T x, T y) 
    { 
     if (typeof(T).IsAssignableFrom(typeof(int))) 
      return new Point2DI { X = (int)(object)x, Y = (int)(object)y }; 

     if (typeof(T).IsAssignableFrom(typeof(double))) 
      return new Point2D { X = (double)(object)x, Y = (double)(object)y }; 

     if (typeof(T).IsAssignableFrom(typeof(float))) 
      return new Point2DF { X = (float)(object)x, Y = (float)(object)y }; 

     throw new Exception("Invalid type parameter"); 
    } 
} 

public class Point2D : Point 
{ 
    public double X { get; set; } 
    public double Y { get; set; } 
} 

public class Point2DF : Point 
{ 
    public float X { get; set; } 
    public float Y { get; set; } 
} 

public class Point2DI : Point 
{ 
    public int X { get; set; } 
    public int Y { get; set; } 
} 
6

我認爲,它能夠更好地去爲仿製藥,因爲這將是更清潔的給你不需要多個類,繼承或其他任何花哨的東西(這將工作過,但國際海事組織不會是乾淨的)

不幸的是,對於數值類型沒有限制,所以這是我想出了這IMO最接近:

public class Point<T> 
    where T : struct, IComparable, IFormattable, IConvertible, IComparable<T>, IEquatable<T> 
{ 

    protected readonly Type[] AllowedTypes = 
     { 
      typeof(decimal), typeof(double), typeof(short), typeof(int), typeof(long), 
      typeof(sbyte), typeof(float), typeof(ushort), typeof(uint), typeof(ulong) 
     }; 

    public Point() 
    { 
     if (!this.AllowedTypes.Contains(typeof(T))) 
     { 
      throw new NotSupportedException(typeof(T).ToString()); 
     }   
    } 

    public T X { get; set; } 

    public T Y { get; set; } 

    // UPDATE: arithmetic operations require dynamic proxy-Properties or 
    // variables since T is not explicitly numeric... :(
    public T CalculateXMinusY() 
    { 
     dynamic x = this.X; 
     dynamic y = this.Y; 

     return x - y; 
    } 
} 

它給你最大。智能感知支持,同時建議主要有效的輸入,但如果使用不當,仍會失敗。所有這些只使用一個乾淨可讀的維護類。

對此,唯一有點醜陋的是巨大的泛型類型約束,但這是C#中所有數字類型的共同之處,所以最好這樣做。

+0

我想我們將無法對此進行算術運算。我也無法獲得T的擴展方法(我們寫了一些)。我想這個問題沒有答案。 –

+0

這是真的,因爲我所有的計算都是在類內部發生的,所以我將所需的值(在您的情況下爲'X'和'Y')分配給'dynamic'變量,這使我能夠對其進行算術計算。也許這有幫助。我會用一個例子更新我的答案。 – nozzleman

+0

更新了我的答案。如果這種情況需要更頻繁的話,那麼您應該考慮購買一種可以「轉換」的受保護財產。但是用這種方法做數學是可能的(儘管它不是最明顯的一種) – nozzleman