1

我有一些类和接口

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 长话短说,但我真的不能给出所有类同种的坐标。

4

3 回答 3

8

那是因为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>只允许您遍历集合,这就是它可以标记为协变的原因。

于 2013-10-21T23:26:45.110 回答
3

您可以将签名更改为:

double GetMinDistance<TGeoObject>(List<TGeoObject> objects, GeoCoordinate position)
    where TGeoObject : IGeoObject 
{
    // ...
}
于 2013-10-21T23:30:01.170 回答
1

您可以定义一个显式(强制转换)或一个隐式运算符,它们采用 aList<User>并将其转换为 a List<IGeoObject>

public static explicit operator List<IGeoObject>(List<IGeoObject> ls)
{
  return new ls.ConvertAll(x => (IGeoObject)x);
}
于 2013-10-21T23:25:59.683 回答