C#のジェネリックメソッドの制約として使用されるジェネリッククラス?

StackOverflow https://stackoverflow.com/questions/313036

  •  10-07-2019
  •  | 
  •  

質問

何か間違ったことをしているのですか、それともジェネリッククラスをジェネリックメソッドの制約として指定することはできませんか?

ジェネリックと db4o (オープンソースオブジェクトデータベース)をいじり、テストを書いています。ユーザー定義の一般的なコレクションを保存および取得するプログラム(以下のコードを参照)。

データベースから特別に型指定されたコレクションを取得するためのジェネリックメソッド(以下の GetCollectionFromDb を参照)を記述しようとしています。残念ながら、以下のコードはその行に対してコンパイラーが生成したエラーを返します。

 MyCollection1 collection3 =
                  GetCollectionFromDb<MyCollection1>(Collection1Name);

エラーメッセージ:

The type 'GenericsTest.MyCollection1'cannot be used as type parameter 'T'
in the generic type or method 'GenericsTest.Program.GetCollectionFromDb<T>(string)'.
There is no implicit reference conversion from'GenericsTest.MyCollection1' to
'GenericsTest.MyCollectionBase<GenericsTest.MyCollection1>'.

私は間違ったことをしている可能性がありますか、またはどうやってこれにアプローチして、望ましい結果に達することができるかについての提案をいただければ幸いです。

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Db4objects.Db4o;

 namespace GenericsTest 
    {
        public class Entity1
        {
            public string SomeProperty { get; set; }
        }

        public class Entity2
        {
            public string SomeProperty { get; set; }
        }

        public abstract class MyCollectionBase<T> : Collection<T>
        {
            protected MyCollectionBase() : this("") { }

            protected MyCollectionBase(string pCollectionName) 
            {
                CollectionName = pCollectionName; 
            }

            public string CollectionName { get; set; }
        }

        public class MyCollection1 : MyCollectionBase<Entity1>
        {
            public MyCollection1(string pCollectionName) :
                                          base(pCollectionName) { }

            public void DoSomeWorkOnCollection1() {}
        }

        public class MyCollection2 : MyCollectionBase<Entity2>
        {
            public MyCollection2(string pCollectionName) :
                                          base(pCollectionName) { }

            public void DoSomeWorkOnCollection2() { }
        }

        public class Program
        {
            public static IObjectContainer db = null;

            public static void Main(string[] args)
            {
                const string Collection1Name = "Entity1Collection";
                const string Collection2Name = "Entity2Collection";
                db = Db4oFactory.OpenFile("Test.db");

                Entity1 entity1 = new Entity1();
                MyCollection1 collection1 = new MyCollection1(Collection1Name);
                collection1.Add(entity1);
                db.Store(collection1);

                Entity2 entity2 = new Entity2();
                MyCollection2 collection2 = new MyCollection2(Collection2Name);
                collection1.Add(entity1);
                db.Store(collection2);

                db.Commit();
                db.Close();
                db = Db4oFactory.OpenFile("Test.db");

                MyCollection1 collection3 = 
                       GetCollectionFromDb<MyCollection1>(Collection1Name);
            }

            private static T GetCollectionFromDb<T>(string pCollectionName) 
                                                 where T : MyCollectionBase<T>
            {
                IList<T> queryResult = db.Query((T c) => 
                                         c.CollectionName == pCollectionName);
                if (queryResult.Count != 0) return queryResult[0];

                return null;
            }
        } 
    }
役に立ちましたか?

解決

Tに従うだけです

    // ...
    {
       //...
       MyCollection1 collection3 = GetCollectionFromDb<MyCollection1>(Collection1Name);

    }

    private static T GetCollectionFromDb<T>(string pCollectionName) where T : MyCollectionBase<T>
    {
        IList<T> queryResult = db.Query((T c) => c.CollectionName == pCollectionName);
        if (queryResult.Count != 0) return queryResult[0];
        return null;
    }

に変換されます:

    private static MyCollection1 GetCollectionFromDb<MyCollection1>(string pCollectionName) where T : MyCollectionBase< MyCollection1 >
    {
        IList< MyCollection1 > queryResult = db.Query((MyCollection1 c) => c.CollectionName == pCollectionName);
        if (queryResult.Count != 0) return queryResult[0];
        return null;
    }

MyCollection1はMyCollectionBase <!> ltから派生しているため、どちらが目的のものではありません。 Entity1 <!> gt; MyCollectionBase <!> lt;ではありません。 MyCollection1 <!> gt;。これがエラーの原因です。制約を機能させたい場合は、おそらく2番目の型識別子を使用して、ジェネリックコレクションで使用されている型を表現する必要があります。

他のヒント

あなたのタイプは制約を満たしていません。 MyCollection1から派生したMyCollection<Entity1>を指定しました。ただし、それはMyCollection<MyCollection1>から派生するという意味ではありません。

おそらく、1つではなく2つの型パラメーターに対する制約を表現する必要があります。

private static T GetCollectionFromDb<T, U>(string pCollectionName) 
                                             where T : MyCollectionBase<U>

次に、次のように呼び出します:

GetCollectionFromDb<MyCollection1, Entity1>(Collection1Name);

それでもうまくいかない場合は、理由をお知らせください。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top