-1

私はすでに悪いサンプルでこの質問を投稿しました。

このコードはより良いはずです。

混乱を避けるために、いくつかのコードを要約しました。

using System.Collections.Generic;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main()
        {
            IManager<ISpecificEntity> specificManager = new SpecificEntityManager();
            IManager<IAntoherSpecificEntity> anotherSpecificManager = new AnotherSpecificEntityManager();
            Dictionary<string, IManager<IIdentifier>> managers = new Dictionary<string, IManager<IIdentifier>>();
            managers.Add("SpecificManager", (IManager<IIdentifier>)specificManager);
            managers.Add("AnotherSpecificManager", (IManager<IIdentifier>)anotherSpecificManager);

            foreach (var manager in managers.Values)
            {
                IIdentifier entity = manager.Container.GetEntity();
            }
        }
    }

    internal interface IIdentifier
    {
        int Id { get; set; }
    }

    internal interface ISpecificEntity : IIdentifier
    {
        string SpecificValue { get; set; }
    }

    internal class SpecificEntity : ISpecificEntity
    {
        public int Id { get; set; }
        public string SpecificValue { get; set; }
    }


    internal interface IAntoherSpecificEntity : IIdentifier
    {
        string AnotherSpecificValue { get; set; }
    }

    internal class AntoherSpecificEntity : IAntoherSpecificEntity
    {
        public int Id { get; set; }
        public string AnotherSpecificValue { get; set; }
    }

    internal interface IContainer<out TIdentifier> where TIdentifier : IIdentifier
    {
        TIdentifier GetEntity();
    }

    internal interface ISpecificContainer : IContainer<ISpecificEntity>
    {
    }

    internal class SpecificContainer : ISpecificContainer
    {
        public ISpecificEntity GetEntity()
        {
            return new SpecificEntity { SpecificValue = "SpecificValue" };
        }
    }

    internal interface IAnotherSpecificContainer : IContainer<IAntoherSpecificEntity>
    {
    }

    internal class AnotherSpecificContainer : IAnotherSpecificContainer
    {
        public IAntoherSpecificEntity GetEntity()
        {
            return new AntoherSpecificEntity { AnotherSpecificValue = "AnotherSpecificValue" };
        }
    }

    internal interface IManager<TIdentifier> where TIdentifier : IIdentifier
    {
        IContainer<TIdentifier> Container { get; set; }
    }

    internal class SpecificEntityManager : IManager<ISpecificEntity>
    {
        public IContainer<ISpecificEntity> Container { get; set; }
    }

    internal class AnotherSpecificEntityManager : IManager<IAntoherSpecificEntity>
    {
        public IContainer<IAntoherSpecificEntity> Container { get; set; }
    }
}

コードをデバッグすると、Main()12 行目で InvalidCastException が発生します。

私はそれがISpecificEntity実装することを知っていますIIdentifierIManager<ISpecificEntity>しかし、明らかに an から anへの直接キャストIManager<IIdentifier>は機能しません。

共分散を操作することでうまくいくと思いましたが、orに変更IManager<TIdentifier>しても機能しません。IManager<in TIdentifier>IManager<out TIdentifier>

それで、にキャストする方法はありspecificManagerますIManager<IIdentifier>か?

ありがとう、そして最高。

4

2 に答える 2

1

まず第一に、ジェネリックの考え方が間違っています。

Foo を見ると、ジェネリック型です。Foo と Foo は新しい型であり、List から派生したものではなく、型が継承によって結合されたものでもありません。ジェネリックを使用すると、新しい型が作成されますが、派生しません!

ただし、探しているのはCovariance と Contravarianceです。これにより、一種の「ジェネリック ポリモーフィズム」を作成できますが、そのためには、ジェネリック定義内でこれを指定する必要があります。したがって、すぐに使用できるごく少数のフレームワーク ジェネリックに対してのみ機能します。

class Program
{
    static void Main(string[] args)
    {
        IManager<IIdentifier> f1 = new C1();
        IManager<IIdentifier> f2 = new SpecificEntityManager(); //IManager<ISpecificEntity>
    }
}

interface IIdentifier { }
interface ISpecificEntity : IIdentifier { }
interface IManager<out T> { }

class C1 : IManager<IIdentifier> { }
class SpecificEntityManager : IManager<ISpecificEntity> { }

変更する必要があるのは次のとおりです。

internal interface IContainer<out TIdentifier> where TIdentifier : IIdentifier 
{ 
    TIdentifier GetEntity(); 
}
internal interface IManager<out TIdentifier> where TIdentifier : IIdentifier 
{
    IContainer<IIdentifier> Container { get; }
}
internal class SpecificEntityManager : IManager<ISpecificEntity>
{
    public IContainer<IIdentifier> Container { get; set; }
}
internal class AnotherSpecificEntityManager : IManager<IAntoherSpecificEntity>
{
    public IContainer<IIdentifier> Container { get; set; }
}
于 2012-04-18T16:08:02.327 に答える
0

IManager<TIdentifier>が継承できる非ジェネリックIManagerは必要ありません。次に、IManager <IIdentifer>はIManagerであり、キャストできますか?

于 2012-04-18T15:56:13.747 に答える