2008-11-23 252 views
0

我做錯了什麼或不可能指定泛型類作爲泛型方法的約束?我一直在玩泛型和db4o(開源對象數據庫),並正在編寫一個測試程序(見下面的代碼)來存儲和檢索一些用戶定義的泛型集合。用作C#中泛型方法約束的泛型類?

我正在嘗試編寫一個通用方法(請參閱下面的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; 
      } 
     } 
    } 

回答

4

只需按照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 < ENTITY1>而不是MyCollectionBase < MyCollection1>這就是你得到錯誤的原因。如果你想約束起作用,你可能必須使用第二個類型標識符來表示在泛型集合中使用的類型。

9

您的類型不符合約束條件。您提供的MyCollection1源自MyCollection<Entity1>。但是,這並不意味着它來自MyCollection<MyCollection1>

也許你想表達的在兩個類型參數,而不是一個約束:

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

然後調用它:

GetCollectionFromDb<MyCollection1, Entity1>(Collection1Name); 

如果不這樣做的伎倆,請告訴我們知道爲什麼。

+0

感謝您的澄清。我接受了布萊恩B的答案,因爲它首先提供了基本相同的信息,儘管沒有簡明表達。 – 2008-11-23 23:00:25