1

このコード:

public interface IInter { }
public class Concrete : IInter { /*... body ...*/ }
var t = (List<IInter>)new List<Concrete>();

次のエラーが発生します。

Cannot convert type 'System.Collections.Generic.List<Concrete>' to 'System.Collections.Generic.List<IInter>'

それはなぜです ?どうすればそれを克服できますか?私の目標はこれです:

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 }
};

だから、もっと複雑だと思います...

私はc#4.0を使用しています

4

6 に答える 6

2
var res = new List<Concrete>().Cast<IInter>().ToList();
于 2013-01-17T15:22:53.293 に答える
2

AList<Concrete> 実装されてList<IInter>い ますが、ではありません。ConcreteIInter

以下を使用できます。

List<IInter> t = ConcreteList.Cast<IInter>().ToList();

共分散と反分散に関するよくある質問

于 2013-01-17T15:23:19.243 に答える
2

これは共分散と呼ばれ、C# はジェネリック クラスではなくジェネリック インターフェイスで共分散 (および反分散) をサポートします。これは次のように動作しますが、あなたの例はそうではありません:

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

共分散は配列でもサポートされています。

IInter[] a = new Concrete[3];
于 2013-01-17T15:26:02.190 に答える
2

List<ConcreteA>aを aに代入することはできないためList<IInter>、それ以外の場合は次のようにできます。

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

あなたがすることができます:

var t = new List<List<IInter>>()
{
    new List<IInter>(){/* ... fill with ConcreteAs ... */},
    new List<IInter>(){/* ... fill with ConcreteBs ... */},
    // ...
    new List<IInter>(){/* ... fill with ConcreteXs ... */},
};

しかし、それがあなたが望むものを達成するかどうかはわかりません。

于 2013-01-17T15:27:57.837 に答える
1

1 つの方法は次のとおりです。

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));
}
于 2013-01-17T15:23:29.617 に答える
1

からアクセスする必要があるメソッドの共変インターフェイスを作成しますSingletonFactory<T>。これにより、タイプ 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 }
};
于 2013-01-25T05:06:52.773 に答える