如何混合泛型和实数类型

本文关键字:泛型 实数 类型 混合 何混合 | 更新日期: 2023-09-27 17:57:36

为什么不允许有这样的泛型类:

class SomeClass<T, int> { ..... }

还可以强制某些类型T为数字,并支持基本运算符,如+、-、*和/。

如何混合泛型和实数类型

因为泛型与C++模板不同;这允许部分专业化。

你当然可以有这个:

public class Generic<T, U> {}
public class Generic2<T> : Generic<T, int> {}

只要第一个泛型中存在于T上的任何泛型约束在第二个泛型上至少重复或更具限制性。

至于你要求的限制,不,你不能。但是,您可以限制为值类型(当然是where T : struct);但这并不真正局限于"数字"。

运算符不包含在类约定中(通过基或接口),因为运算符是静态定义的,并且对于表达式a op b,运算符可以出现在两种类型T(a)T(b)中的任何一种上。

因此,不可能基于类型约束来定义类型约束。

然而,您可以定义自己的契约——就像这样(这里的实现很幼稚,完全不完整,只是为了演示,in a wall of code(tm)):

(查看最后的泛型,看看它是否有效)

public abstract class MyNumeric
{
  public abstract object ValueObject { get; }
  public abstract MyNumeric Add(MyNumeric other);
  public abstract MyNumeric Substract(MyNumeric other);
  public abstract MyNumeric Multiply(MyNumeric other);
  public abstract MyNumeric Divide(MyNumeric other);
  public static MyNumeric operator +(MyNumeric a, MyNumeric b)
  {
    return a.Add(b);
  }
  public static MyNumeric operator -(MyNumeric a, MyNumeric b)
  {
    return a.Substract(b);
  }
  public static MyNumeric operator *(MyNumeric a, MyNumeric b)
  {
    return a.Multiply(b);
  }
  public static MyNumeric operator /(MyNumeric a, MyNumeric b)
  {
    return a.Divide(b);
  }
  //etc
}
public abstract class MyNumeric<T> : MyNumeric
  where T : struct
{
  public override object ValueObject { get{ return this.Value;}}
  public new T Value { get; private set; }
  public MyNumeric(T value) { Value = value; }
}
public class MyInt : MyNumeric<int>
{
  public MyInt(int value) : base(value) { }
  public override MyNumeric Add(MyNumeric other)
  {
    //could be really crafty here and use an interface instead that
    //gives access to the Value part only - that way you could
    //have MyDouble, for example, implement INumeric<int> explicitly 
    //via a c# explicit conversion.
    MyNumeric<int> otherInt = other as MyNumeric<int>;
    if (otherInt == null)
      throw new ArgumentException(
        "Need to handle numeric promotion/demotion for all types", "other");
    return new MyInt(Value + otherInt.Value);
  }
  public override MyNumeric Divide(MyNumeric other)
  {
    throw new NotImplementedException();
  }
  public override MyNumeric Multiply(MyNumeric other)
  {
    throw new NotImplementedException();
  }
  public override MyNumeric Substract(MyNumeric other)
  {
    throw new NotImplementedException();
  }
}
public class MyGeneric<TNumeric> where TNumeric : MyNumeric
{
  public TNumeric WillNowCompile(TNumeric a, TNumeric b)
  {
    //cast is still required on the result.
    //however - you can set the return type to MyNumeric instead if you want.
    return (TNumeric)(a + b);
  }
  public TNumeric AnotherOne<TNumeric2>(TNumeric a, TNumeric2 b)
    where TNumeric2 : MyNumeric
  {
    return (TNumeric)(a / b);
  }
}

但是,正如我在代码中所说,您必须考虑如何处理int+double这样的情况。但这可以作为一个起点来完成。

通用T参数允许对类正在使用的参数类型不特定。

如果要使用int,请在类中使用int。如果您想规定类中的某个东西必须是int,那么可以通过公共方法或构造函数的参数来实现。

对运算符的支持将取决于它自己传入的类型。如果您已为该类型重写了运算符,则一旦在类中使用,它就会支持它。不能对未知泛型执行此操作。

对于问题的第二部分,您可以执行以下操作:

class MyClass<T>  where T : IEquatable<T>, IComparable<T>

不存在所有数字的父类,但它们确实实现了这些接口。