c#泛型:简化类型签名

本文关键字:类型 泛型 | 更新日期: 2023-09-27 18:09:47

如果我有一个通用的Item类,看起来像这样:

abstract class Item<T>
{
}

和一个容器的项目看起来像这样:

class Container<TItem, T>
    where TItem : Item<T>
{
}

由于item依赖于T,是否有可能简化Container的类型签名,使其只接受一个类型参数?我真正想要的是这样的东西:

class Container<TItem>
    where TItem : Item   // this doesn't actually work, because Item takes a type parameter
{
}

所以我可以像这样实例化它:

class StringItem : Item<string>
{
}
var good = new Container<StringItem>();
var bad = new Container<StringItem, string>();

当tiitem是StringItem时,编译器应该能够推断出T是string,对吗?我该怎么做呢?

的用法:

class MyItem : Item<string>
{
}
Container<MyItem> container = GetContainer();
MyItem item = container.GetItem(0);
item.MyMethod();

c#泛型:简化类型签名

我认为这应该是你想要的。显然,你现在做的是Container<string>而不是Container<StringItem>,但由于你没有包括使用示例,我不认为这是一个问题。

using System.Collections.Generic;
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var myContainer = new Container<string>();
            myContainer.MyItems = new List<Item<string>>();
        }
    }
    public class Item<T> { }
    public class Container<T>
    {
        // Just some property on your container to show you can use Item<T>
        public List<Item<T>> MyItems { get; set; }
    }
}

修改后的版本如何:

using System.Collections.Generic;
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var myContainer = new Container<StringItem>();
            myContainer.StronglyTypedItem = new StringItem();
        }
    }
    public class Item<T> { }
    public class StringItem : Item<string> { }
    // Probably a way to hide this, but can't figure it out now
    // (needs to be public because it's a base type)
    // Probably involves making a container (or 3rd class??)
    // wrap a private container, not inherit it
    public class PrivateContainer<TItem, T> where TItem : Item<T> { }
    // Public interface
    public class Container<T> : PrivateContainer<Item<T>, T>
    {
        // Just some property on your container to show you can use Item<T>
        public T StronglyTypedItem { get; set; }
    }
}

我认为你的问题的一个可能的解决方案是添加接口IItem和代码结构将如下所示。

interface IItem { }
abstract class Item<T> : IItem { }
class Container<TItem> where TItem : IItem { }
class StringItem: Item<string> { }

现在你可以得到Container<StringItem>:

var container = new Container<StringItem>();