简体   繁体   English

泛型类用作C#中泛型方法的约束吗?

[英]Generic class used as constraint to generic method in C#?

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. 我一直在研究泛型和db4o (开放源代码对象数据库),并且正在编写一个测试程序(请参见下面的代码)以存储和检索一些用户定义的泛型集合。

I am attempting to write a generic method (see GetCollectionFromDb below) to retrieve a specifically typed collection from the database. 我试图编写一个通用方法(请参见下面的GetCollectionFromDb )以从数据库中检索特定类型的集合。 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;
            }
        } 
    }

Your type doesn't satisfy the constraint. 您的类型不满足约束。 You've supplied MyCollection1 which derives from MyCollection<Entity1> . 您已经提供了MyCollection1 ,它是从MyCollection<Entity1>派生的。 However, that doesn't mean it derives from MyCollection<MyCollection1> . 但是,这并不意味着它派生自MyCollection<MyCollection1>

Perhaps you want to express the constraint over two type parameters instead of one: 也许您想对两个类型参数而不是一个参数表达约束:

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

Then call it with: 然后调用:

GetCollectionFromDb<MyCollection1, Entity1>(Collection1Name);

If that doesn't do the trick, please let us know why. 如果这样做不能解决问题,请告诉我们原因。

Just follow the T: 只需遵循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;
    }

would translate into: 将转换为:

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

Which is not what you want since MyCollection1 derives off MyCollectionBase< Entity1 > and not MyCollectionBase< MyCollection1 >, which is why you got the error. 这不是您想要的,因为MyCollection1派生自MyCollectionBase <Entity1>而不是MyCollectionBase <MyCollection1>,这就是您收到错误的原因。 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. 如果希望约束起作用,则可能必须使用第二个类型标识符来表示泛型集合中使用的类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM