有以下一个泛型抽象基类,定义了一个供子类覆盖的静态方法,用于描述某个子类的一些信息,同时提供一个属性用来获取这个信息:public abstract class MembersBase<T> where T : new()  
    {  
         public static string Info
         {
          get
          {
          return typeof(T).InvokeMember("GetString",System.Reflection.BindingFlags.Static|System.Reflection.BindingFlags.InvokeMethod|System.Reflection.BindingFlags.Public,null,null,null) as string;
          }
         }
        public static string GetString()
        {
          return "base";
        }
    }  之后在子类中重写方法:public class a : MembersBase<a>  
    {  
        public a():base(){}  
        public static new string GetString()
        {
        return "a class";
        }
    }  
    public class b : MembersBase<b>  
    {  
        public b():base(){}  
        public static new string GetString()
        {
        return "b class";
        }
    } 调用是这样的:a ai=new a();
      b bi=new b();
      Console.WriteLine(a.Info);
      Console.WriteLine(b.Info);现在的目的是需要将a、b放入一个List集合,但使用
List<MemberBase> lm=new List<MemberBase>();
出现编译错误
求一个创建泛型抽象基类list的方法

解决方案 »

  1.   

    有以下一个泛型抽象基类,定义了一个供子类覆盖的静态方法
    在我的知识结构中,静态方法是不可以继承的~所以也就没有什么 供子类覆盖的静态方法
    public class MembersBase
    {
    public  vir string GetString()
            {
            return "MembersBase class";
            }
    }
    public class a : MembersBase
        { 
            public override string GetString()
            {
            return "a class";
            }
        }  
        public class b : MembersBase  
        {  
            public override string GetString()
            {
            return "b class";
            }
        } ListMembersBase<T> : List<T>  where T : MembersBase 大概思想如此~ 
      

  2.   

    本帖最后由 caozhy 于 2013-09-11 12:22:53 编辑
      

  3.   


    还是说目的吧,现在有这样一个目的:
    1.公开一个规范(基类)供开发拓展,这个规范需要有一个静态成员用于获取此类的描述符,用于代表此类已确定的、不改变的特性。
    2.描述符可能是另一个类或结构体,所以不能用attribute描述
    3.如果子类没有重写描述符,返回默认描述符
    4.这个类实际上是一个完整的功能模块,所以用一个静态成员来描述是最简单的做法(不需要在注册拓展时进行大量配置或在加载拓展时进行额外的一次初始化)。
    实在是想破了头才想出泛型基类+覆盖方法这个方式,自己也知道不合适,但一时间想不到其他方法了,还请赐教
    另外静态方法可以在子类中继承访问吧,只是不能标记为虚方法供重写,所以才用了new关键字覆盖。
    刚才看了msdn上的ReferenceEquals方法,说明是:确定指定的 Object 实例是否是相同的实例。 (从 Object 继承。)。这个不是继承么?
      

  4.   

    面向对象的关键一点是“对象”而不是“类型”
    如果不是面向“对象”的问题就不要用面向对象的思想来解决。事实上针对你的这个问题,attribute恰恰是最适合的做法,却被你先否定了。
      

  5.   

    按照你的说法,静态成员就不应该有存在的意义,面向对象的编程就应该完全舍弃静态成员---与对象无关么,这是属于类型的
    我对你的理解能力深感佩服,这一手偷换概念玩的真好,为你鼓掌。
    好吧,不在这上面争论,只看具体事例:如果不用静态成员的话如何获取用于描述某个类特性的结构体?用一个特别长、特别复杂的attribute来符合所谓的“面向对象思想”真的比一个静态成员更为好用?
    还有,现在说的是示例解决方案,不是什么面向对象思想,什么事都往XXX思想上面扯,阁下的思维逻辑也让在下大为惊讶。
      

  6.   

    按照你的说法,静态成员就不应该有存在的意义,面向对象的编程就应该完全舍弃静态成员---与对象无关么,这是属于类型的
    我对你的理解能力深感佩服,这一手偷换概念玩的真好,为你鼓掌。
    好吧,不在这上面争论,只看具体事例:如果不用静态成员的话如何获取用于描述某个类特性的结构体?用一个特别长、特别复杂的attribute来符合所谓的“面向对象思想”真的比一个静态成员更为好用?
    还有,现在说的是示例解决方案,不是什么面向对象思想,什么事都往XXX思想上面扯,阁下的思维逻辑也让在下大为惊讶。
    这不是静态成员不成员的问题,使用静态成员你就要考虑如何去取这个静态成员,如果是直接取的话,那相当于你需要认识每一个子类的,而且还要分别处理。所以只能是通过反射来获取。
    既然是反射,那么attribute是比较正常的想法。当然,你的需求也许是信息很复杂,attribute写起来不方便,那你就做成静态成员反射去呗,毕竟没人拦着你。
    再回到最初,你的a类和b类是一点关系都没有的两个类,就好像List<int>和List<String>除了继承相同的接口外其实是不相关的两个类型。
    再重复一遍,继承是对象的概念,静态的东西没有继承的说法。所以不管你的需求最后如何解决,编译时的检查必然是用不上的,只能是运行时检查。
      

  7.   

    用抽象基类是可以满足要求的,描述符有默认的实现。
    也可以List<>
      

  8.   

    按照你的说法,静态成员就不应该有存在的意义,面向对象的编程就应该完全舍弃静态成员---与对象无关么,这是属于类型的
    我对你的理解能力深感佩服,这一手偷换概念玩的真好,为你鼓掌。
    好吧,不在这上面争论,只看具体事例:如果不用静态成员的话如何获取用于描述某个类特性的结构体?用一个特别长、特别复杂的attribute来符合所谓的“面向对象思想”真的比一个静态成员更为好用?
    还有,现在说的是示例解决方案,不是什么面向对象思想,什么事都往XXX思想上面扯,阁下的思维逻辑也让在下大为惊讶。
    这不是静态成员不成员的问题,使用静态成员你就要考虑如何去取这个静态成员,如果是直接取的话,那相当于你需要认识每一个子类的,而且还要分别处理。所以只能是通过反射来获取。
    既然是反射,那么attribute是比较正常的想法。当然,你的需求也许是信息很复杂,attribute写起来不方便,那你就做成静态成员反射去呗,毕竟没人拦着你。
    再回到最初,你的a类和b类是一点关系都没有的两个类,就好像List<int>和List<String>除了继承相同的接口外其实是不相关的两个类型。
    再重复一遍,继承是对象的概念,静态的东西没有继承的说法。所以不管你的需求最后如何解决,编译时的检查必然是用不上的,只能是运行时检查。
    ReferenceEquals  确定指定的 Object 实例是否是相同的实例。 (从 Object 继承。)
    摘自MSDN任何一个类型的成员页面。
    在该例中,基类 BaseC 和派生类 DerivedC 使用相同的字段名 x,从而隐藏了继承字段的值。该示例演示了 new 修饰符的用法。另外还演示了如何使用完全限定名访问基类的隐藏成员。
    public class BaseC
    {
        public static int x = 55;
        public static int y = 22;
    }public class DerivedC : BaseC
    {
        // Hide field 'x'.
        new public static int x = 100;    static void Main()
        {
            // Display the new value of x:
            Console.WriteLine(x);        // Display the hidden value of x:
            Console.WriteLine(BaseC.x);        // Display the unhidden member y:
            Console.WriteLine(y);
        }
    }
    摘自MSDN new 修饰符(C# 参考):http://msdn.microsoft.com/zh-cn/library/435f1dw2%28v=vs.90%29.aspx
    原来微软都不理解面向对象的含义,居然能继承静态成员
      

  9.   

    按照你的说法,静态成员就不应该有存在的意义,面向对象的编程就应该完全舍弃静态成员---与对象无关么,这是属于类型的
    我对你的理解能力深感佩服,这一手偷换概念玩的真好,为你鼓掌。
    好吧,不在这上面争论,只看具体事例:如果不用静态成员的话如何获取用于描述某个类特性的结构体?用一个特别长、特别复杂的attribute来符合所谓的“面向对象思想”真的比一个静态成员更为好用?
    还有,现在说的是示例解决方案,不是什么面向对象思想,什么事都往XXX思想上面扯,阁下的思维逻辑也让在下大为惊讶。
    这不是静态成员不成员的问题,使用静态成员你就要考虑如何去取这个静态成员,如果是直接取的话,那相当于你需要认识每一个子类的,而且还要分别处理。所以只能是通过反射来获取。
    既然是反射,那么attribute是比较正常的想法。当然,你的需求也许是信息很复杂,attribute写起来不方便,那你就做成静态成员反射去呗,毕竟没人拦着你。
    再回到最初,你的a类和b类是一点关系都没有的两个类,就好像List<int>和List<String>除了继承相同的接口外其实是不相关的两个类型。
    再重复一遍,继承是对象的概念,静态的东西没有继承的说法。所以不管你的需求最后如何解决,编译时的检查必然是用不上的,只能是运行时检查。
    还有,取attribute有特定的方法GetCustomAttributes,用反射完全是多此一举
      

  10.   

    new 和 override 或者说覆盖和继承是完全完全不相关的两个东西,希望你能理解了这个前提再来讨论这个问题,不然我觉得就是在浪费大家的时间。
      

  11.   

    按照你的说法,静态成员就不应该有存在的意义,面向对象的编程就应该完全舍弃静态成员---与对象无关么,这是属于类型的
    我对你的理解能力深感佩服,这一手偷换概念玩的真好,为你鼓掌。
    好吧,不在这上面争论,只看具体事例:如果不用静态成员的话如何获取用于描述某个类特性的结构体?用一个特别长、特别复杂的attribute来符合所谓的“面向对象思想”真的比一个静态成员更为好用?
    还有,现在说的是示例解决方案,不是什么面向对象思想,什么事都往XXX思想上面扯,阁下的思维逻辑也让在下大为惊讶。
    这不是静态成员不成员的问题,使用静态成员你就要考虑如何去取这个静态成员,如果是直接取的话,那相当于你需要认识每一个子类的,而且还要分别处理。所以只能是通过反射来获取。
    既然是反射,那么attribute是比较正常的想法。当然,你的需求也许是信息很复杂,attribute写起来不方便,那你就做成静态成员反射去呗,毕竟没人拦着你。
    再回到最初,你的a类和b类是一点关系都没有的两个类,就好像List<int>和List<String>除了继承相同的接口外其实是不相关的两个类型。
    再重复一遍,继承是对象的概念,静态的东西没有继承的说法。所以不管你的需求最后如何解决,编译时的检查必然是用不上的,只能是运行时检查。
    还有,取attribute有特定的方法GetCustomAttributes,用反射完全是多此一举
    你越说越可笑了,我现在已经怀疑你究竟对C#了解多少,也许基础知识还没弄明白吧。GetCustomAttributes就是反射啊,大哥,你究竟知道不知道什么叫做反射?找本正经的书好好看看吧,别这么丢人了好不。
      

  12.   


    还是说目的吧,现在有这样一个目的:
    1.公开一个规范(基类)供开发拓展,这个规范需要有一个静态成员用于获取此类的描述符,用于代表此类已确定的、不改变的特性。
    2.描述符可能是另一个类或结构体,所以不能用attribute描述
    3.如果子类没有重写描述符,返回默认描述符
    4.这个类实际上是一个完整的功能模块,所以用一个静态成员来描述是最简单的做法(不需要在注册拓展时进行大量配置或在加载拓展时进行额外的一次初始化)。
    实在是想破了头才想出泛型基类+覆盖方法这个方式,自己也知道不合适,但一时间想不到其他方法了,还请赐教
    另外静态方法可以在子类中继承访问吧,只是不能标记为虚方法供重写,所以才用了new关键字覆盖。
    刚才看了msdn上的ReferenceEquals方法,说明是:确定指定的 Object 实例是否是相同的实例。 (从 Object 继承。)。这个不是继承么?(1)什么是描述符,它是干嘛的。如果你用的术语不是广泛意义上人们熟知的,请你在使用前先定义它。
    (2、3)因为我不知道什么是描述符,我就更不知道为什么不能用Attribute定义,以及为什么要用Attrbiute定义。
    (4)这个类实际上是一个完整的功能模块,所以用一个静态成员来描述是最简单的做法。什么是完整的功能,你用静态成员描述什么?用静态成员描述一个类?为什么是最简单的做法,和什么相比简单?
    (5)不知道你提ReferenceEquals做什么。估计我之前没有说的很清楚。你当然可以从一个类的派生类去访问基类的静态成员。或许你把这个当作静态成员可以继承了。如果是这样,怪我没有说清楚。我想表达的是,你没有办法在派生类中编写一个方法去“覆盖”基类的静态方法。好比你举的例子,你new一个方法,基类如果不知道派生类中的这个GetString,它永远不可能调用到,我再用代码解释下:class A
    {
        public static string GetString() { return "a"; }
        void foo()
        {
            string s1 = GetString(); // always pass "a"
            string s2 = B.GetString(); // "b"
        }
    }class B : A
    {
        public new static string GetString() { return "b"; }
        void foo()
        {
            string s1 = GetString(); // always pass "b"
            string s2 = A.GetString(); // "a"
        }
    }
      

  13.   

    你想想看,如果要访问派生类的方法需要知道派生类的类型,那这样的“继承”还有意义么?那么你又要说了,我可以反射。恭喜你,答对了。你通过反射可以绕过面向对象的全部准则,无拘无束地访问任何你想要的东西。但是我说了,这和继承已经没有关系了。对于上例,那个B : A完全是装装样子的,你不让B继承A也可以通过反射让A调用B的GetString方法。甚至你为什么管B的GetString叫"GetString"呢,叫别的也没关系。类似的,你也没有必要装模作样地使用List<MembersBase>了。它还装不进去基于MembersBase<a>的a类的对象,你干脆用List<object>或者ArrayList好了。我们需要明确一点,你不懂面向对象的任何思想,你一样可以用自己发明的古怪方式编写出任何想要的程序。我对这一点毫不怀疑。因为无论是面向对象的C#还是别的语言,最终都能通过编译器的转换,得到连面向过程都不是的CPU指令序列,用数学的观点说,它们都是图灵等价的。但是在这个过程中,你非要把那些你不理解的东西,比如泛型啦、继承啦往里面套,就一点也不必要了。当然,在你理解了编写C#程序的一般准则后,你就不会按照你的臆想去设计程序,并且生搬硬套一些概念和语法,并且在“编译不过去”的时候再用更加稀奇古怪地方式来达成你的目标。也不会在买到一袋面包的时候钻牛角尖地说“既然你生产的是食品,并且提供了包装袋,那就一定要保证包装袋也可以吃”。