如何通过泛型使用嵌套类列表创建基类列表而无需强制转换

时间:2019-03-25 10:38:20

标签: c# .net generics collections

我想为ICollection<T2>提供一个扩展方法,让女巫返回我IReadOnlyCollection<T1>。我需要的所有这些都是为了避免在代码中重复我自己。我有以下代码:

public static IReadOnlyCollection<T1> All<T1, T2>(this ICollection<T2> storage) where T1 : T2
{
    if (storage.Count > 0)
    {
        return new List<T1>(storage);
    }
    else
    {
        return new List<T1>();
    }
}

但是不幸的是它不能编译。 因此,让我们看一下上面的一个简单示例:

public interface IDatabase {}
public class Database : IDatabase, IDisposable {}

public static IReadOnlyCollection<T1> All<T1, T2>(this ICollection<T2> storage) where T2 : T1 where T1 : new()
{
    // compiles
    List<Database> derivedList = new List<PublishedDatabase>();
    List<IDatabase> baseList = new List<IPublishedDatabase>(derivedList);

    // doesn't compile
    // with casting it works
    List<T2> derivedListT = new List<T2>();
    List<T1> baseList1T = new List<T1>(derivedListT/* as IEnumerable<T1>*/);

    //...
}

我可以通过泛型使用嵌套类列表创建基类列表吗?

2 个答案:

答案 0 :(得分:1)

我可能在这里误解了约束,但是您可以暂时使用dynamic来使分析器蒙蔽

public static IReadOnlyCollection<T1> All<T1, T2>(this ICollection<T2> storage) where T2: T1
{
    dynamic temp = storage;
    return new ReadOnlyCollection<T1>(new List<T1>(temp));
}

...

var list = new List<SomeChild>()
               {
                  new SomeChild()
               };

var interfaces = list.All<ISomeBase, SomeChild>();

注意 :如果您的代码分析器在抱怨强制转换,则您会认为他们对dynamic的抱怨甚至会更难。 ..也是完全未经测试的,也许有更好的方法可以做到这一点

答案 1 :(得分:0)

您可以像这样简化扩展方法的代码

public static IReadOnlyCollection<T1> All<T1>(this ICollection<T1> storage)
        {
            if(storage.Count > 0)
            {
                return new List<T1>(storage);
            }
            else
            {
                return new List<T1>();
            }
        }

然后您可以这样称呼它:

public static void Run()
        {
           ICollection<IDatabase> databases= new List<IDatabase>(){ new Database()};
           databases.All();
        }