Am I doing something wrong or is it not possible to specify a generic class as a constraint to a generic method?
I have been playing around with generics and db4o (open source object database) and am writing a test program (see code below) to store and retrieve some user defined generic collections.
I am attempting to write a generic method (see GetCollectionFromDb below) to retrieve a specifically typed collection from the database. Unfortunately, the code below returns a compiler generated error for the line:
MyCollection1 collection3 = GetCollectionFromDb<MyCollection1>(Collection1Name);
The error message is:
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>'.
I would appreciate any suggestions as to what I may be doing wrong or how I could approach this differently to reach the deisred outcome.
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; } } }
Just follow the T:
would translate into:
Which is not what you want since MyCollection1 derives off MyCollectionBase< Entity1 > and not MyCollectionBase< MyCollection1 >, which is why you got the error. If you want the constraint to work, you will probably have to use a second type identifier to express the type being used in the generic collection.