2008-11-23 103 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