为什么不允许这样的泛型类:
class SomeClass<T, int> { ..... }
也可以强制某些类型T为数字并支持基本运算符,如+, - ,*和/。
答案 0 :(得分:3)
因为泛型与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
等情况。但是可以用它作为起点来完成。
答案 1 :(得分:2)
泛型T
参数允许对该类正在使用的参数类型进行非特定。
如果您想使用int
,请在课程中使用int
。如果你想要规定类中的某些东西必须是int
,那么可以通过公共方法或构造函数的参数来完成。
对运算符的支持将是它自己传入的类型。如果你已经覆盖了类型的运算符,那么它将在类中使用它。你不能在未知的通用上这样做。
答案 2 :(得分:0)
对于问题的第二部分,您可以这样做:
class MyClass<T> where T : IEquatable<T>, IComparable<T>
所有数字都没有父类,但是它们确实实现了这些接口。