2016-01-18 21 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