通用集合中的协方差C#

Ale*_*ndr 1 .net c# generics

我有一些类和接口

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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

我有,类型的示例变量用户 List<User>

我有签名的方法

double GetMinDistance(List<IGeoObject> objects, GeoCoordinate position)
Run Code Online (Sandbox Code Playgroud)

我无法传递用户GetMinDistance,因为泛型类型的协方差不起作用.

我可以创建额外的列表和使用方法.ConvertAll(或.CasT<T>):

List<IGeoObject> list = new List<User>(listUser).ConvertAll(x => (IGeoObject)x);
var dist = GeoTest.GetMinDistance(list, position);
Run Code Online (Sandbox Code Playgroud)

我不确定这是最优雅的解决方案.最令人尴尬的是调用者必须进行此转换.

这类似于我在架构中的问题?有更优雅的解决方案吗?

PS长篇故事,但我真的不能给出所有班级中同一物种的坐标.

Mar*_*zek 8

那是因为List<T>不协变.

public class List<T> : IList<T>, ICollection<T>, 
    IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, 
    IEnumerable
Run Code Online (Sandbox Code Playgroud)

如您所见,out类声明中没有关键字.

您必须使用它IEnumerable<T>来获得协方差支持.

public interface IEnumerable<out T> : IEnumerable
Run Code Online (Sandbox Code Playgroud)

那是因为List<T>有一组允许你修改集合的方法,并且使用协方差你将失去这些操作的编译类型安全性.IEnumerable<T>只允许你迭代集合,这就是为什么它可以被标记为协变.