c# - 通用集合 C# 中的协方差

标签 c# .net generics

我有一些类和接口(interface)

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);

我不确定这是最优雅的解决方案。最尴尬的是,调用者必须执行此转换

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

附言说来话长,但我真的不能给出所有类中同一物种的坐标。

最佳答案

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

关于c# - 通用集合 C# 中的协方差,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19506511/

相关文章:

java - 该语句中的第一个 <U> 是什么意思?

c# - 创建 StructureMap 容器的克隆

c# - .NET + 复制大量内存技巧

c# - 多线程时锁定单个 bool 变量?

c# - .NET 中的 zlib 实现是否良好?

c# - 如何将 Field<T> 与类型一起使用?

c# - 泛型参数的构造函数要求?

c# - BooleanToVisibilityConverter 与 Caliburn.Micro 一起使用的奇怪行为

c# - 在 Visual Studio 中扩展 "Tools"窗口

c# - 如何将 .NET 4 的 XmlConvert.IsWhitespaceChar 向后移植到 .NET 3.5?