[英]When to use a non-generic interface as a generic type constraint
我正在努力尋找一種使用非通用接口作為通用類型約束的方案。 下面是一個任意示例,其中非泛型方法(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);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.