繁体   English   中英

通用集合中的协方差C#

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM