在try 实现泛型时,我注意到具有实现接口的泛型的类与具有扩展基类的泛型的类之间存在不同的行为.使用接口时,我不能调用接受接口类型的可枚举数的函数,但使用类时,一切都很好.下面是一个例子

public interface IBarInterface
{
    public int Value { get; set; }
}

public class FooInterface<TInterface> where TInterface : IBarInterface
{
    private List<TInterface> _items;

    public List<TInterface> Items => _items;

    // Does not compile:
    //  Argument type 'System.Collections.Generic.List<TInterface>' is not assignable to parameter type 'System.Collections.Generic.IEnumerable<IBarInterface>'
    public bool SomeValue => Processors.DoSomethingInterface(_items);

    public FooInterface()
    {
        _items = new List<TInterface>();
    }
}

public class BarClass
{
    public int Value { get; set; }
}

public class FooClass<TClass> where TClass : BarClass
{
    private List<TClass> _items;

    public List<TClass> Items => _items;

    // Does compile
    public bool SomeValue => Processors.DoSomethingClass(_items);

    public FooClass()
    {
        _items = new List<TClass>();
    }
}

public static class Processors
{
    public static bool DoSomethingInterface(IEnumerable<IBarInterface> items)
        => items.Count() % 2 == 0;

    public static bool DoSomethingClass(IEnumerable<BarClass> items)
        => items.Count() % 2 == 0;
}

FooInterface无法编译,但FooBar编译得很好.为何会是这样呢?

推荐答案

在这种情况下,接口和类之间的关键区别是structs也可以实现接口!协方差/逆方差转换(如从IEnumerable<Subtype>转换为IEnumerable<Supertype>)仅在SubtypeSupertype都是参考类型时才可用.

FooClass<TClass>的情况下,TClass被约束为BarClass的子类,因此TClass必须是引用类型.

FooInterface<TInterface>的情况下,TInterface仅被约束为IBarInterface的实现,因此它也可以是struct.在DoSomethingInterface(_items)不能保证协方差转换是有效的.

因此,如果您只是确保TInterface不能是值类型,

where TInterface : class, IBarInterface

那么错误就会消失.

Csharp相关问答推荐

获取Windows和Linux上的下载文件夹

无法更改或使用C#(WinForms.NET)中的全局变量

Microsoft.AspNetCore.Mvc. Controller Base.用户:属性或索引器Controller Base.用户无法分配给--它是只读的

有没有一种方法可以在包含混合文本的标签中嵌入超链接?

在. NET Core 8 Web API中,当为服务总线使用通用消费者时,如何防止IServiceProvider被释放或空?"

Elasticsearch:当我try 使用c#将嵌套对象添加到filter中时出现问题

NumPy s fftn in C#with pythonnet'

如何注销Microsoft帐户?

此反射有什么问题.是否发送值转换委托?

当用户右键单击文本框并单击粘贴时触发什么事件?

在C#中,将两个哈希集连接在一起的时间复杂度是多少?

HelperText属性不支持复杂内容(混合C#和标记)

为值对象编写自定义JsonConverter

如何在.NET Maui中将事件与MVVM一起使用?

如何将%{v_扩展}转换为%{v_扩展}>>

为什么Azure函数(独立工作进程)索引失败?使用Azure App配置的CosmosDbTrigger绑定失败,未解析为值

发布.NET 8 Blazor WebAssembly独立应用程序以进行静态站点部署

C# Winforms:从对象树到TreeView的递归转换重复条目

如何在Polly重试策略成功之前将HttpClient请求排队?

如何在绑定到数据库的datagridview中向上或向下移动行