何时使用非泛型接口作为泛型类型约束
本文关键字:泛型类型 约束 泛型接口 何时使 | 更新日期: 2023-09-27 18:33:17
我正在努力寻找一种使用非泛型接口作为泛型类型约束的场景。下面是一个任意示例,其中非泛型方法 (RideCar2) 比泛型方法 RideCar 更简单。
class Program
{
static void Main(string[] args)
{
var car = new Merc();
RideCar(car);
RideCar2(car);
}
static void RideCar<T>(T t) where T : ICar
{
t.StartEngine();
t.StopEngine();
}
static void RideCar2(ICar car)
{
car.StartEngine();
car.StopEngine();
}
}
public interface ICar
{
void StartEngine();
void StopEngine();
}
public class Merc : ICar
{
public void StartEngine() { Console.WriteLine("Merc start"); }
public void StopEngine() { Console.WriteLine("Merc stop"); }
}
很明显,RideCar2是一个更好的实现,因为它的噪音更少。
是否存在用作泛型类型约束的非泛型接口有意义的方案?
更多例子(根据答复)
- 用作返回类型
static T RideCar(T t) where T : ICar
{
t.StartEngine();
t.StopEngine();
return t;
}
使用普通方法仍然会使泛型方法的使用毫无用处,请参见下文:
static ICar RideCar(ICar car)
{
car.StartEngine();
car.StopEngine();
return car;
}
- 多个接口
static void RideCar(T t) where T : ICar, ICanTimeTravel
{
t.StartEngine(); // ICar
t.TravelToYear(1955); // ICanTimeTravel
t.StopEngine(); // ICar
}
使用具有多个参数的普通方法仍然会使泛型方法的使用毫无用处,请参见下文:
static void RideCar(ICar car, ICanTimeTravel canTimeTravel)
{
car.StartEngine();
canTimeTravel.TravelToYear(1955);
car.StopEngine();
}
是的,有。考虑:
static T RideCar<T>(T t) where T : ICar
{
t.StartEngine();
t.StopEngine();
return t;
}
这将返回特定类型。现在,您可以使用实现细节,而不必将其转换回实现类型,这是不好的做法。
此外,您可以对同一泛型参数具有多个接口约束:
static void RideCar<T>(T t) where T : ICar, ICanTimeTravel
{
t.StartEngine(); // ICar
t.TravelToYear(1955); // ICanTimeTravel
t.StopEngine(); // ICar
}
最后,即使这有时被认为是代码异味,您也可以将new()
约束与接口约束一起使用,以便在方法中创建实现类型的实例:
static T Create<T>() where T : ICar, new()
{
T t = new T();
return t;
}
这取决于。在您的情况下,非通用方式是首选。
如果要调用在不同接口上声明的方法,则使用类型约束的泛型声明是有意义的:
public void Test<T>(T value, T other)
where T: IEquatable<T>, IComparable<T>
{
value.Equals(other); //in IEquatable<T>
value.CompareTo(other); //in IComparable<T>
}
但在这种情况下,如果可能的话,我更喜欢使用基类,并在以下方法中使用它,没有任何类型约束:
public class BaseCar<T> : IEquatable<T>, IComparable<T>, ICar
{
/// [...]
}
public void Test<T>(BaseCar<T> car1, BaseCar<T> car2)
where T: IEquatable<T>, IComparable<T>
{
car1.Equals(car2);
car1.CompareTo(car2);
}
或没有泛型,但仅限于 ICar:
public class BaseCar : IEquatable<ICar>, IComparable<ICar>
{
/// [...]
}
public void Test(BaseCar car1, BaseCar car2)
{
car1.Equals(car2);
car2.CompareTo(car2);
}