繁体   English   中英

C#的Python风格的类方法?

[英]Python-style classmethod for C#?

有没有办法在C#中使用classmethod在Python中做什么?

也就是说,一个静态函数可以根据它使用的子类将Type对象作为(隐式)参数。

我想要的一个例子就是

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.

(这里在键盘上的代码相同。)

我想你想看看泛型。

MSFT指南:

http://msdn.microsoft.com/en-us/library/ms379564(VS.80).aspx

根据上下文,您可能需要泛型或虚拟方法。

原则上,你可以写这样的东西:

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)同样简洁且更惯用时,是否有理由这样写呢? 可能不是。

这相当于Object Pascal中的类方法。 (.Net实现将是RemObject的oxygene)。

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

我曾经在Oxygene中编程好几年,而且我从不需要类引用。

不是因为我不知道如何使用它们。 在“原始” ObjectPascal平台,原生德尔福,我用他们所有的时间。 但是因为.Net和BCL对它们没有真正的支持,所以使用它们没有任何好处。 而像python或本机Delphi这样的平台确实在他们的库中支持它们。

您显然不需要静态方法,您想要的是可以具有状态和/或支持继承的东西。 所以无论是工厂,还是在你的情况下,构造函数也可以。

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

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

暂无
暂无

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

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