类型不能在泛型类型或方法中用作类型参数“T” - 为什么? [英] Type cannot be used as type parameter 'T' in the generic type or method - Why?

查看:1629
本文介绍了类型不能在泛型类型或方法中用作类型参数“T” - 为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从接口继承两个不同的模型。这些模型应该作为List或Collection传递给Method。现在我收到此错误消息:

I'm trying inherit two different Models from a Interface. These Models should be passed either as List or Collection to a Method. Now I'm getting this error message:

The type 'InheritanceTest.FooModel' cannot be used as type parameter 'T' in the generic type or method 'InheritanceTest.Service.DoSomethingWith<T>(System.Collections.Generic.IEnumerable<T>)'. There is no implicit reference conversion from 'InheritanceTest.FooModel' to 'InheritanceTest.IModel<InheritanceTest.IModelItem>'. C:\Work\InheritanceTest\InheritanceTest\Program.cs 14 13 InheritanceTest

有人可以请解释一下,我做错了什么? :D

Can somebody please explain me, what I'm doing wrong? :D

演示代码:

interface IModel<T> where T : IModelItem
{
    string Name { get; set; }

    IEnumerable<T> Items { get; set; }
}

interface IModelItem
{
    string Name { get; set; }
}

class FooModel : IModel<FooModelItem>
{
    public FooModel()
    {
        Items = new List<FooModelItem>();
    }

    public string Name { get; set; }
    public IEnumerable<FooModelItem> Items { get; set; }
}

class FooModelItem : IModelItem
{
    public string Name { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var fooLists = new List<FooModel>();
        var barLists = new ObservableCollection<BarModel>();

        var service = new Service();

        service.DoSomethingWith(fooLists);
        service.DoSomethingWith(barLists);
    }
}

class Service
{
    public void DoSomethingWith<T>(IEnumerable<T> list) where T : IModel<IModelItem>
    {
        foreach (var model in list)
        {
            Debug.WriteLine(model.Name);

            foreach (var item in model.Items)
            {
                Debug.WriteLine(item.Name);
            }
        }
    }
}

演示项目可以在GitHub找到:
https:// github .com / SunboX / InheritanceTest / blob / master / InheritanceTest / Program.cs

The Demo Project can be found at GitHub: https://github.com/SunboX/InheritanceTest/blob/master/InheritanceTest/Program.cs

推荐答案

作为原因的一个例子你不能这样做,想象除了 FooModel FooModelItem ,你还有 BarModelItem 。现在让我们说你这样做:

As an example of why you can't do this, imagine that in addition to FooModel and FooModelItem, you had BarModelItem. Now let's say you do this:

IModel<FooModelItem> fooModel = new FooModel();
IModel<IModelItem> iModel = fooModel;
iModel.Items = new List<BarModelItem>(new BarModelItem());

FooModelItem fooModelItem = fooModel.Items.First();

如果这是有效的代码,你会遇到麻烦,因为你会收到这个项目在最后一行实际上不是 FooModelItem 但是 BarModelItem

If this was valid code, you'd be in trouble, because the item you'd get back in the last line would not in fact be a FooModelItem but a BarModelItem!

如果仔细阅读每一行,您将看到唯一可能的错误行是第二行。这说明了为什么无法将 IModel< FooModelItem> 分配给 IModel< IModelItem> ,即使 FooModelItem:IModelItem 。无法执行该分配正是您的方法调用失败的原因。

If you read each line carefully, you will see that the only possible wrong line is the second one. This demonstrates why an IModel<FooModelItem> can't be assigned to an IModel<IModelItem>, even though FooModelItem : IModelItem. Not being able to do that assignment is exactly why your method call fails.

您可以查看通用协方差和逆变,以了解在某些情况下如何避免这种情况,如果不修改你的模型,它对你的特殊情况没有帮助。

You can look into generic covariance and contravariance to see how this can be avoided in some cases, though it won't help in your particular situation without modifying your model.

这篇关于类型不能在泛型类型或方法中用作类型参数“T” - 为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆