代码之家  ›  专栏  ›  技术社区  ›  AKX Bryan Oakley

C#的Python风格的类方法?

  •  6
  • AKX Bryan Oakley  · 技术社区  · 16 年前

    classmethod Python中的C#?

    我想要的一个例子大概是

    class Base:
        @classmethod
        def get(cls, id):
            print "Would instantiate a new %r with ID %d."%(cls, id)
    
    class Puppy(Base):
        pass
    
    class Kitten(Base):
        pass
    
    p = Puppy.get(1)
    k = Kitten.get(1)
    

    Would instantiate a new <class __main__.Puppy at 0x403533ec> with ID 1.
    Would instantiate a new <class __main__.Kitten at 0x4035341c> with ID 1.
    

    (same code on codepad here.)

    5 回复  |  直到 16 年前
        1
  •  2
  •   Juliet    16 年前

    原则上,你 能够

    class Base
    {
        public static T Get<T>(int id)
            where T : Base, new()
        {
            return new T() { ID = id };
        }
    
        public int ID { get; set; }
    }
    

    然后你就可以写了 var p = Base.Get<Puppy>(10) . 或者,如果你感到受虐狂,你可以写信 Puppy.Get<Puppy>(10) Kitty.Get<Puppy> ;) 在所有情况下,都必须显式传递类型,而不是隐式传递。

    或者,这也适用于:

    class Base<T> where T : Base<T>, new()
    {
        public static T Get(int id)
        {
            return new T() { ID = id };
        }
    
        public int ID { get; set; }
    }
    
    class Puppy : Base<Puppy>
    {
    }
    
    class Kitten : Base<Kitten>
    {
    }
    

    您仍然需要将类型传递回基类,这样就可以编写 Puppy.Get(10)

    但是,还有什么理由这样写吗 var p = new Puppy(10)

        2
  •  3
  •   Hamish Grubijan    16 年前
        3
  •  2
  •   ICR    16 年前

    根据上下文的不同,您需要泛型或虚拟方法。

        4
  •  0
  •   Robert Giesecke    16 年前

    然而,虽然类引用和虚拟类方法或看似静态的方法(它们可以访问某些类级别的状态)在原始平台中很好,但我认为它们对.Net或C#没有多大意义。

    不是因为我不知道如何使用它们。在“原始”ObjectPascal平台原生Delphi中,我使用了它们 时间。 但是因为.Net和BCL对它们没有真正的支持,所以使用它们没有任何优势。而python或native Delphi等平台在其库中确实支持它们。

        5
  •  0
  •   data George    11 年前

    因为C#是静态编译的,所以调用 Puppy.get() 在编译时解析,例如,已知指向 Base.get() 这意味着生成的CIL(公共中间语言)将有一个调用指令 :

    .method private hidebysig static void  Main() cil managed
    {
      .entrypoint
      // Code size       9 (0x9)
      .maxstack  8
      IL_0000:  nop
      IL_0001:  ldc.i4.1
      IL_0002:  call       void Base::get(int32)
      IL_0007:  nop
      IL_0008:  ret
    }