1

私がこの取り決めを持っているとしましょう:

    public interface ICreatable
    {
        int CreatedByUserId { get; set; }
    }

    public class Unicorn : ICreatable
    {
        public int CreatedByUserId { get; set; }
    }

    public interface ICrudService<T>
        where T : class, ICreatable
    {
        T DoSomething(T t);
    }

    public class UnicornService : ICrudService<Unicorn>
    {
        public Unicorn DoSomething(Unicorn unicorn)
        {
            var createdByUserId = unicorn.CreatedByUserId;

            // ...

            return unicorn;
        }
    }

そして、次のように使用します。

    static void Main(string[] args)
    {
        var unicorn = new Unicorn();
        var unicornService = new UnicornService();

        unicornService.DoSomething(unicorn);
    }

これはうまくいきます。ただし、インターフェイス型として、ジェネリック型と一緒にunicornServiceインターフェイス型としてキャストしたいとしましょう。ICrudService

        var crudService = unicornService as ICrudService<ICreatable>;

問題が発生しました。これはどのように見えるかです:

unicornService as ICrudService<Unicorn> --> casts is fine
unicornService as ICrudService<ICreatable> --> casts to null

それUnicorn以来ICreatableICrudService<T> where T: class, ICreatableこれを解決するのに問題はないはずです。私の検索は共分散と反分散に私を導き始めましたが、私はそのレベルで迷子になっています。

crudServiceにキャストするにはどうすればよいICrudService<ICreatable>ですか?

アップデート:

共分散を次のように使用します。

    public interface ICrudService<out T>

次に、インテリセンスに「無効な分散: 型パラメーター 'T' は 'ICrudService.DoSomething(T)' で反変的に有効である必要があります。'T' は共変です。」これはどのように作動しますか?

4

2 に答える 2

0

ICrudService<Unicorn>を として扱うことはできませんICrudService<ICreatable>

オブジェクトはのタイプまたはサブタイプのICrudService<Unicorn>パラメータのみを受け入れることができますが、は のパラメータを受け入れることができます。 UnicornUnicornICrudService<ICreatable>SomeOtherTypeOfICreatable

タイプは、 だけでなく、 にUnicornService固有のメンバーを使用できます。これは、その機能が制限されているタイプであるためです。その制限により、より一般的なインターフェイスの API を満たすことができなくなります。UnicornICreatable

要するに、それは不可能です。

于 2013-10-07T16:51:03.797 に答える
0

out T修飾子を使用するには、T の代わりにICreatableを受け入れるように DoSomething を変更する必要があります。

public interface ICrudService<out T>
    where T : class, ICreatable
{
    T DoSomething(ICreatable t);
}

public class UnicornService : ICrudService<Unicorn>
{
    public Unicorn DoSomething(ICreatable t)
    {
        var unicorn = (Unicorn)t;
        var createdByUserId = unicorn.CreatedByUserId; // or t.CreatedByUserId

        // ...

        return unicorn;
    }
}

非 Unicorn が UnicornService に渡される場合、このコードは例外をスローすることに注意してください。

于 2013-10-07T16:59:09.030 に答える