С# общие ограничения
Можно ли перечислять типы, которые "доступны" в общем ограничении?
T MyMethod<t>() where T : int, double, string
Почему я хочу это сделать, так это то, что у меня есть небольшой механизм оценки и хотел бы
напишите код следующим образом:
bool expression.Evaluate<bool>();
или
int expression.Evaluate<int>();
но я хочу запретить
MyCustomClass expression.Evalaute<MyCustomClass>();
Ответы
Ответ 1
Невозможно ограничить общий аргумент конкретными типами.
В качестве обходного пути вы можете предоставить метод для каждого типа и перенаправить вызовы метода на общую реализацию:
public class Expression {
public bool EvaluateToBool() {
return Evaluate<bool>();
}
public int EvaluateToInt32() {
return Evaluate<int>();
}
private T Evaluate<T>() {
return default(T);
}
}
С другой стороны, подумали ли вы о кодировании типа, которое выражение выражает в типе выражения? Например.
public abstract class Expression<T> {
public abstract T Evaluate();
}
public sealed class AddExpression : Expression<int> {
public AddExpression(Expression<int> left, Expression<int> right) {
this.Left = left;
this.Right = right;
}
public Expression<int> Left { get; private set; }
public Expression<int> Right { get; private set; }
public override int Evaluate() {
return this.Left.Evaluate() + this.Right.Evaluate();
}
}
Ответ 2
Если у вас есть небольшое количество возможностей для аргумента generic type, этот метод не является действительно общим. Точка дженериков состоит в том, чтобы разрешить параметризацию типов и методов, чтобы вы могли создавать бесконечно много разных типов и методов по требованию. Если у вас есть только три возможных типа, напишите три метода. То есть, создавайте перегрузки, не используйте дженерики.
Ответ 3
Нет, вы не можете.
Вы можете добавить следующее общее ограничение:
T MyMethod<T>() where T : struct {}
И затем:
bool expression.MyMethod<bool>(); //OK
int expression.MyMethod<int>(); //OK
string expression.MyMethod<string>(); //fails! string is a reference type
struct MyStruct {}
MyStruct MyMethod<MyStruct>(); //OK! MyStruct is a value type
class MyCustomClass {}
MyCustomClass MyMethod<MyCustomClass>(); //FAILS! MyCustomClass is a reference type
Но вы не можете добавлять ограничения времени компиляции для int и string одновременно.