Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/neo4j/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何将嵌套泛型转换为从第一个嵌套泛型继承的另一个嵌套泛型?_C#_Generics - Fatal编程技术网

C# 如何将嵌套泛型转换为从第一个嵌套泛型继承的另一个嵌套泛型?

C# 如何将嵌套泛型转换为从第一个嵌套泛型继承的另一个嵌套泛型?,c#,generics,C#,Generics,此代码: public interface IInter { } public class Concrete : IInter { /*... body ...*/ } var t = (List<IInter>)new List<Concrete>(); 产生以下错误: 无法将类型“System.Collections.Generic.List”转换为“System.Collections.Generic.List” 为什么?我如何克服它?我的目标是: var t =

此代码:

public interface IInter { }
public class Concrete : IInter { /*... body ...*/ }
var t = (List<IInter>)new List<Concrete>();
产生以下错误:

无法将类型“System.Collections.Generic.List”转换为“System.Collections.Generic.List”

为什么?我如何克服它?我的目标是:

var t = new List<List<IInter>>()
{
    new List<ConcreteA>(){/* ... data ... */},
    new List<ConcreteB>(){/* ... data ... */},
    // ...
    new List<ConcreteX>(){/* ... data ... */},
};
编辑: 谢谢你的帮助。啊,我有点抽象的东西,让它更容易阅读。。。但我真正的问题是:

public class SingletonFactory<T> where T : IToken
{
    private SingletonFactory() { }
    private static SingletonFactory<T> _instance = new SingletonFactory<T>();
    public static SingletonFactory<T> Instance { get { return _instance; } }

    public T Produce(int position) { return (T)Activator.CreateInstance(typeof(T), position); }
    public T Produce(int position, string token) { return (T)Activator.CreateInstance(typeof(T), position, token); }
}
然后:

var keywords = new Dictionary<string, SingletonFactory<IToken>>()
{
    { "abc", SingletonFactory<Abc>.Instance },
    { "xyz", SingletonFactory<Xyz>.Instance },
    { "123", SingletonFactory<Num>.Instance }
};
所以我想这要复杂得多

我使用的是C4.0,虽然具体实现了IInter,但列表不是列表

var res = new List<Concrete>().Cast<IInter>().ToList();
您可以使用:

List<IInter> t = ConcreteList.Cast<IInter>().ToList();
列表不是列表,尽管具体实现了IInter

您可以使用:

List<IInter> t = ConcreteList.Cast<IInter>().ToList();
一种方法是:

IEnumerable<IInter> t = new List<Concrete>();
另一个是:

List<IInter> t = new List<Concrete>().ConvertAll(x => (IInter) x);
编辑,添加更好的样本,以显示其在测试通过时有效:

[Test]
public void CovarianceTest()
{
    var concrete = new Concrete();
    IEnumerable<IInter> t = new List<Concrete> { concrete };
    Assert.IsTrue(new[] { concrete }.SequenceEqual(t));

    List<IInter> t2 = new List<Concrete> { concrete }.ConvertAll(x => (IInter)x);
    Assert.IsTrue(new[] { concrete }.SequenceEqual(t2));
}
一种方法是:

IEnumerable<IInter> t = new List<Concrete>();
另一个是:

List<IInter> t = new List<Concrete>().ConvertAll(x => (IInter) x);
编辑,添加更好的样本,以显示其在测试通过时有效:

[Test]
public void CovarianceTest()
{
    var concrete = new Concrete();
    IEnumerable<IInter> t = new List<Concrete> { concrete };
    Assert.IsTrue(new[] { concrete }.SequenceEqual(t));

    List<IInter> t2 = new List<Concrete> { concrete }.ConvertAll(x => (IInter)x);
    Assert.IsTrue(new[] { concrete }.SequenceEqual(t2));
}
这被调用,C支持泛型接口上的协方差和逆变,而不是泛型类。以下是可行的,但您的示例不可行:

IEnumerable<IInter> e = new List<Concrete>();
ICollection<IInter> c = new List<Concrete>();
这被调用,C支持泛型接口上的协方差和逆变,而不是泛型类。以下是可行的,但您的示例不可行:

IEnumerable<IInter> e = new List<Concrete>();
ICollection<IInter> c = new List<Concrete>();

由于无法将列表分配给列表,否则可以执行以下操作:

concreteAList = newList<ConcreteA>();
List<Inter> interList = concreteAList as List<Inter>;  // seems harmless
interList.Add(new ConcreteB());                        // not allowable
你可以做:


但我不知道这是否满足了您的要求。

因为您无法将列表分配给列表,否则您可以执行以下操作:

concreteAList = newList<ConcreteA>();
List<Inter> interList = concreteAList as List<Inter>;  // seems harmless
interList.Add(new ConcreteB());                        // not allowable
你可以做:


但是我不知道这是否满足了您的需要。

为您需要从SingletonFactory访问的方法创建一个covrariant接口。这将确保您的类型T是输出类型安全的

public interface IToken { }
public class Abc : IToken { }
public class Xyz : IToken { }
public class Num : IToken { }

public interface ISingletonFactory<out T> where T : IToken
{
    T Produce(int position);
    T Produce(int position, string token);
}

public class SingletonFactory<T> : ISingletonFactory<T> where T : IToken
{
    private SingletonFactory() { }
    private static SingletonFactory<T> _instance = new SingletonFactory<T>();
    public static SingletonFactory<T> Instance { get { return _instance; } }

    public T Produce(int position) { return (T)Activator.CreateInstance(typeof(T), position); }
    public T Produce(int position, string token) { return (T)Activator.CreateInstance(typeof(T), position, token); }
}

var keywords = new Dictionary<string, ISingletonFactory<IToken>>()
{
    { "abc", SingletonFactory<Abc>.Instance },
    { "xyz", SingletonFactory<Xyz>.Instance },
    { "123", SingletonFactory<Num>.Instance }
};

为需要从SingletonFactory访问的方法创建一个covrariant接口。这将确保您的类型T是输出类型安全的

public interface IToken { }
public class Abc : IToken { }
public class Xyz : IToken { }
public class Num : IToken { }

public interface ISingletonFactory<out T> where T : IToken
{
    T Produce(int position);
    T Produce(int position, string token);
}

public class SingletonFactory<T> : ISingletonFactory<T> where T : IToken
{
    private SingletonFactory() { }
    private static SingletonFactory<T> _instance = new SingletonFactory<T>();
    public static SingletonFactory<T> Instance { get { return _instance; } }

    public T Produce(int position) { return (T)Activator.CreateInstance(typeof(T), position); }
    public T Produce(int position, string token) { return (T)Activator.CreateInstance(typeof(T), position, token); }
}

var keywords = new Dictionary<string, ISingletonFactory<IToken>>()
{
    { "abc", SingletonFactory<Abc>.Instance },
    { "xyz", SingletonFactory<Xyz>.Instance },
    { "123", SingletonFactory<Num>.Instance }
};

你确定我们能写第一行吗?我不知道这一点,也无法让它发挥作用。愿它是新的列表而不是新的List@MehmetAtaş是的,因为IEnumerable是协变的,所以您无法向基础列表添加其他类型OK,我也进行了测试,现在我清楚了。它适用于FW>=4.0,不适用于FW<4.0:第一种方法很好,但我真正的问题是抱歉没有首先提到它-请看我的编辑是使用字典。第二行将更改对象的行为。您确定我们可以写入第一行吗?我不知道这一点,也无法让它发挥作用。愿它是新的列表而不是新的List@MehmetAtaş是的,因为IEnumerable是协变的,所以您无法向基础列表添加其他类型OK,我也进行了测试,现在我清楚了。它适用于FW>=4.0,不适用于FW<4.0:第一种方法很好,但我真正的问题是抱歉没有首先提到它-请看我的编辑是使用字典。第二行将更改对象的行为。您确定我们可以写入第一行吗?我不知道这一点,也无法让它发挥作用。愿它是新的列表而不是新的List@MehmetAtaş:事实上,我第一次是对的,该死的,你的自我怀疑。通用接口的协方差是在.NET4中添加的,所以您可能正在使用早期版本?我做了一些测试,现在我清楚了。它适用于FW>=4.0,而不适用于FW<4.0:我使用C4.0,有没有办法也使用字典?参见我的编辑?@Tal,IDictionary fruits=new Dictionary;你确定我们能写第一行吗?我不知道这一点,也无法让它发挥作用。愿它是新的列表而不是新的List@MehmetAtaş:事实上,我第一次是对的,该死的,你的自我怀疑。通用接口的协方差是在.NET4中添加的,所以您可能正在使用早期版本?我做了一些测试,现在我清楚了。它适用于FW>=4.0,而不适用于FW<4.0:我使用C4.0,有没有办法也使用字典?参见我的编辑?@Tal,IDictionary fruits=new Dictionary;