8

ジェネリック インターフェイス (名前空間 Sample2 を参照) を宣言して使用し、名前空間 Sample1 のクラスと同じように動作させるにはどうすればよいですか?

回避策があることは知っていますが (名前空間 Sample2Modified を参照)、それは私が達成しようとしているものではありません。


クラスで動作

クラスを使用する場合、これは正常に機能します。

namespace Sample1
{
    public class ClassContainer<T1, T2>
        where T1 : T2
    { }

    public class ClassParent
    { }

    public class ClassChild : ClassParent
    { }

    public class ClassSampleDoesWork<TItem>
        where TItem : ClassParent
    {
        ClassContainer<IEnumerable<TItem>, IEnumerable<ClassParent>> SomeProperty { get; set; }
    }
}

インターフェイスでは機能しません

ただし、インターフェイスを使用すると、ClassSampleDoesNotWork でプロパティを宣言するときに、コンパイラによって次の警告が表示されます。

Error 16 The type 'System.Collections.Generic.IEnumerable<TItem>'
cannot be used as type parameter 'T1' in the generic type or method
'Sample2.IInterfaceContainer<T1,T2>'. There is no implicit reference
conversion from 'System.Collections.Generic.IEnumerable<TItem>' to
'System.Collections.Generic.IEnumerable<Sample2.IInterfaceParent>'.

コード:

namespace Sample2
{
    public interface IInterfaceContainer<T1, T2>
        where T1 : T2
    { }

    public interface IInterfaceParent
    { }

    public interface IInterfaceChild : IInterfaceParent
    { }

    public class ClassSampleDoesNotWork<TItem>
        where TItem : IInterfaceParent
    {
        IInterfaceContainer<IEnumerable<TItem>, IEnumerable<IInterfaceParent>> SomeProperty { get; set; }
    }
}

変更されたバージョンは機能しますが、これは私が本当に望んでいるものではありません

TItem の代わりに TEnumerableOfItem を持つようにクラスを変更すると、次のように動作します。

namespace Sample2Modified
{
    public interface IInterfaceContainer<T1, T2>
        where T1 : T2
    { }

    public interface IInterfaceParent
    { }

    public interface IInterfaceChild : IInterfaceParent
    { }

    public class ClassSampleModifiedDoesWork<TEnumerableOfItem>
        where TEnumerableOfItem : IEnumerable<IInterfaceParent>
    {
        IInterfaceContainer<TEnumerableOfItem, IEnumerable<IInterfaceParent>> SomeProperty { get; set; }
    }
}
4

1 に答える 1

5

classに制約を追加してみてくださいTItem:

namespace Sample2
{
    public interface IInterfaceContainer<T1, T2>            
        where T1 : T2
    { }

    public interface IInterfaceParent
    { }

    public interface IInterfaceChild : IInterfaceParent
    { }

    public class ClassSampleDoesNotWork<TItem>
        where TItem : class, IInterfaceParent
    {
        IInterfaceContainer<IEnumerable<TItem>, IEnumerable<IInterfaceParent>> SomeProperty { get; set; }
    }
}

これが機能するのは、分散が参照型に対してのみ機能する (または ID 変換がある) ためです。を追加しない限り、それTItemが参照型であることがわかりません: class詳細については、この記事をお読みください。この動作を示すサンプル コードを次に示します。

IEnumerable<Object> items = new List<int>(); // Compiler error.
于 2013-07-08T14:25:31.637 に答える