[英]Covariance in generic collections C#
我有一些类和接口
public interface IGeoObject
{
GeoCoordinate GetGeocoordinate();
}
public class User : IGeoObject
{
public GeoCoordinate GetGeocoordinate()
{
//...
return GeoCoordinate;
}
}
public class Venue : IGeoObject
{
public GeoCoordinate GetGeocoordinate()
{
//...
return GeoCoordinate;
}
}
public class Place : IGeoObject
{
public GeoCoordinate GetGeocoordinate()
{
//...
return GeoCoordinate;
}
}
我有类型为List<User>
示例变量用户
而且我有签名的方法
double GetMinDistance(List<IGeoObject> objects, GeoCoordinate position)
我无法将用户传递给GetMinDistance
,因为通用类型的协方差不起作用。
我可以创建其他列表并使用方法.ConvertAll
(或.CasT<T>
):
List<IGeoObject> list = new List<User>(listUser).ConvertAll(x => (IGeoObject)x);
var dist = GeoTest.GetMinDistance(list, position);
我不确定这是否是最优雅的解决方案。 最尴尬的是, 调用者必须进行此转换 。
这类似于我的体系结构问题吗? 还有更优雅的解决方案吗?
PS长话大说,但我确实不能在所有课程中都给出相同物种的坐标。
这是因为List<T>
不是协变的。
public class List<T> : IList<T>, ICollection<T>,
IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>,
IEnumerable
如您所见,类声明中没有out
关键字。
您必须使用IEnumerable<T>
来获得协方差支持。
public interface IEnumerable<out T> : IEnumerable
这是因为List<T>
具有一组允许您修改集合的方法,并且由于协方差,您将失去这些操作的编译类型安全性。 IEnumerable<T>
仅允许您遍历集合,因此可以将其标记为协变。
您可以将签名更改为:
double GetMinDistance<TGeoObject>(List<TGeoObject> objects, GeoCoordinate position)
where TGeoObject : IGeoObject
{
// ...
}
您可以定义一个采用List<User>
并将其转换为List<IGeoObject>
的显式( List<IGeoObject>
)或隐式运算符。
public static explicit operator List<IGeoObject>(List<IGeoObject> ls)
{
return new ls.ConvertAll(x => (IGeoObject)x);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.