views:

82

answers:

4

Is there a way to do what classmethod does in Python in C#?

That is, a static function that would get a Type object as an (implicit) parameter according to whichever subclass it's used from.

An example of what I want, approximately, is

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)

the expected output being

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

+3  A: 

I think you want to take a look at generics.

Guide from MSFT:

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

Hamish Grubijan
+2  A: 

Depending on the context, you either want generics or virtual methods.

ICR
+1  A: 

In principle, you could write something like this:

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

    public int ID { get; set; }
}

Then you could write var p = Base.Get<Puppy>(10). Or, if you were feeling masochistic, you could write Puppy.Get<Puppy>(10) or even Kitty.Get<Puppy> ;) In all cases, you have to pass in the type explicitly, not implicitly.

Alternatively, this works too:

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

You still need to pass the type back up to the base class, which allows you to write Puppy.Get(10) as expected.

But still, is there a reason to write it like that when var p = new Puppy(10) is just as concise and more idiomatic? Probably not.

Juliet
A: 

This is equivalent to class methods in Object Pascal. (a .Net implementation would be RemObject's oxygene).

However, while class references and thus virtual class methods or seemingly static methods which can kinda access some class-level state are nice in there original platform, I don't think they make much sense for .Net or C#.

I used to also program in Oxygene for several years, and I never needed class references.

Not because I didn't know how to use them. In the "original" ObjectPascal platform, native Delphi, I used them all the time. But because .Net and the BCL have no real support for them, so you do not have any advantages by using them. Whereas platforms like python or native Delphi do support them in their libraries.

You obviously do not want a static method, what you want is something that can have state and/or supports inheritance. So either factories, or in your case a constructor might be fine as well.

Robert Giesecke