فئة عامة تستخدم القيد إلى عامة الأسلوب في C# ؟

StackOverflow https://stackoverflow.com/questions/313036

  •  10-07-2019
  •  | 
  •  

سؤال

أفعل شيء خاطئ أو أنه لا يمكن تحديد فئة عامة باعتباره قيدا على عامة الأسلوب ؟

لقد لعب حولها مع الأدوية ، db4o (المصدر المفتوح كائن قاعدة البيانات) و أكتب برنامج الاختبار (انظر التعليمات البرمجية أدناه) لتخزين واسترجاع بعض يحددها المستخدم ومجموعات عامة.

أنا محاولة لكتابة طريقة عامة (انظر 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>'.

وسأكون ممتنا أي اقتراحات بشأن ما يمكن أن يكون به خطأ أو كيف يمكنني أن هذا النهج بشكل مختلف للوصول إلى deisred النتيجة.

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;
            }
        } 
    }
هل كانت مفيدة؟

المحلول

فقط اتبع 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 > الذي هو السبب في أنك حصلت على خطأ.إذا كنت تريد القيد أن العمل سوف يكون على الارجح الى استخدام النوع الثاني معرف للتعبير عن نوع المستخدمة في جمع عام.

نصائح أخرى

نوع لا يرضي القيد.لقد زودت MyCollection1 التي تستمد من MyCollection<Entity1>.بيد أن هذا لا يعني أنه مستمد من MyCollection<MyCollection1>.

ربما كنت ترغب في التعبير عن القيد أكثر من نوع المعلمات بدلا من واحد:

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

ثم اتصل مع:

GetCollectionFromDb<MyCollection1, Entity1>(Collection1Name);

إذا لم تفعل خدعة ، واسمحوا لنا أن نعرف لماذا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top