Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to make classmethods in C# like python?

In python, an instance method self points to the class instance, just like this in C#. In python, a class method self points to the class. Is there a C# equivalent?

This can be useful, example:

Python example:

class A:
  values = [1,2]

  @classmethod
  def Foo(self):
    print "Foo called in class: ", self, self.values

  @staticmethod
  def Bar():
    print "Same for all classes - there is no self"

class B(A):
  # other code specific to class B
  values = [1,2,3]
  pass

class C(A):
  # other code specific to class C
  values = [1,2,3,4,5]
  pass

A.Foo()
A.Bar()
B.Foo()
B.Bar()
C.Foo()
C.Bar()

Results in:

Foo called in class:  __main__.A [1, 2]
Same for all classes - there is no self
Foo called in class:  __main__.B [1, 2, 3]
Same for all classes - there is no self
Foo called in class:  __main__.C [1, 2, 3, 4, 5]
Same for all classes - there is no self

This can be a great tool so that common code in a class context (without an instance) can provide customised behaviour that is defined by the subclass (without requiring an instance of the subclass).

It seems to me that C# static methods are exactly like pythons static methods, in that there is no access to which class was actually used to invoke the method.

But is there a way to do class methods in C#?? Or at least determine which class invoked a method, for example:

public class A
{
  public static List<int> values;

  public static Foo()
  {
    Console.WriteLine("How can I figure out which class called this method?");
  }
}

public class B : A
{
}

public class C : A
{
}

public class Program
{
  public static void Main()
  {
    A.Foo();
    B.Foo();
    C.Foo();
  }
}
like image 607
Matt Connolly Avatar asked Sep 01 '25 23:09

Matt Connolly


2 Answers

There is no way to do this using regular static methods. Possible alternatives include:

1) Virtual, overridden instance methods:

public class A
{
    public virtual void Foo()
    {
        Console.WriteLine("Called from A");
    }
}

public class B : A
{
    public override void Foo()
    {
        Console.WriteLine("Called from B");
    }
}

2) Extension methods:

public class A
{
}

public class B : A
{
}

public static class Extensions
{
    /// Allows you to do:
    /// var whoop = new B();
    /// whoop.Foo();
    public static void Foo<T>(this T thing) where T : A
    {
        Console.WriteLine("Called from " + thing.GetType().Name);
    }
}

3) Assuming A and B have a default constructor:

public static class Cached<T> where T : class, new()
{
    private static T _cachedInstance;

    public static T Instance
    {
        get { return _cachedInstance ?? (_cachedInstance = new T()); }
    }
}

public static class Extensions
{
    public static void Example()
    {
        Cached<B>.Instance.Foo();
    }

    public static void Foo<T>(this T thing) where T : A, new()
    {
        Console.WriteLine("Called from " + typeof(T).Name);
    }
}
like image 117
Chris Shain Avatar answered Sep 03 '25 11:09

Chris Shain


Not as such. Each calling method would have to push itself and the this variable onto some staticly-available stack or dictionary.

You could explore using CallContext to store the calling stack. I once used such a mechanism to store stack-based information on a function call chain.

You could use an AOP framework like Postsharp to handle the CallContext stuff. That's what I did. I used it for this exact purpose. I was embedding IronPython into my app, and wanted a way to identify the C# object and method that initiated a call into IronPython. It worked pretty well. Unfortunately, I do not have that code anymore.


Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!