Frage

Mache ich etwas falsch oder ist es nicht möglich, eine generische Klasse als ein Hemmnis für eine generische Methode angeben?

Ich habe mit Generika Herumspielen und db4o (Open Source Objektdatenbank) und schreibe einen Test Programm (siehe Code unten) einige benutzerdefinierte generische Sammlungen zu speichern und abzurufen.

Ich versuche, eine generische Methode (siehe GetCollectionFromDb unten) zu schreiben, um eine speziell typisierte Sammlung aus der Datenbank abgerufen werden. Leider Sie den Code unten gibt einen Compiler erzeugt Fehler für die Zeile:

 MyCollection1 collection3 =
                  GetCollectionFromDb<MyCollection1>(Collection1Name);

Die Fehlermeldung lautet:

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>'.

würde ich irgendwelche Vorschläge zu schätzen wissen, was ich falsch machen kann oder wie ich das anders angehen könnte das deisred Ergebnis zu erreichen.

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;
            }
        } 
    }
War es hilfreich?

Lösung

Folgen Sie einfach der 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;
    }

würde übersetzen in:

    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;
    }

Was ist nicht das, was Sie wollen, da MyCollection1 off leitet MyCollectionBase und nicht MyCollectionBase , weshalb Sie den Fehler bekam. Wenn Sie die Einschränkung arbeiten wollen, werden Sie wahrscheinlich einen zweiten Typ Bezeichner verwenden, um die Art auszudrücken in der generischen Sammlung verwendet werden.

Andere Tipps

Ihre Art erfüllt nicht die Einschränkung. Sie haben MyCollection1 geliefert, die von MyCollection<Entity1> ableitet. Doch das bedeutet nicht, es aus MyCollection<MyCollection1> ableitet.

Vielleicht möchten Sie die Einschränkung über zwei Parameter des Typs auszudrücken statt eines:

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

Dann rufen Sie es mit:

GetCollectionFromDb<MyCollection1, Entity1>(Collection1Name);

Wenn das nicht funktioniert der Trick tun, lassen Sie es uns wissen, warum.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top