C# virtual static method

21,941

Solution 1

virtual means the method called will be chosen at run-time, depending on the dynamic type of the object. static means no object is necessary to call the method.

How do you propose to do both in the same method?

Solution 2

Eric Lippert has a blog post about this, and as usual with his posts, he covers the subject in great depth:

https://docs.microsoft.com/en-us/archive/blogs/ericlippert/calling-static-methods-on-type-parameters-is-illegal-part-one

“virtual” and “static” are opposites! “virtual” means “determine the method to be called based on run time type information”, and “static” means “determine the method to be called solely based on compile time static analysis”

Solution 3

Guys who say that there is no sense in static virtual methods - if you don't understand how this could be possible, it does not mean that it is impossible. There are languages that allow this!! Look at Delphi, for example.

Solution 4

The contradiction between "static" and "virtual" is only a C# problem. If "static" were replaced by "class level", like in many other languages, no one would be blindfolded.

Too bad the choice of words made C# crippled in this respect. It is still possible to call the Type.InvokeMember method to simulate a call to a class level, virtual method. You just have to pass the method name as a string. No compile time check, no strong typing and no control that subclasses implement the method.

Some Delphi beauty:

type
  TFormClass = class of TForm;
var
  formClass: TFormClass;
  myForm: TForm;
begin
  ...
  formClass = GetAnyFormClassYouWouldLike;
  myForm = formClass.Create(nil);
  myForm.Show;
end

Solution 5

I'm going to be the one who naysays. What you are describing is not technically part of the language. Sorry. But it is possible to simulate it within the language.

Let's consider what you're asking for - you want a collection of methods that aren't attached to any particular object that can all be easily callable and replaceable at run time or compile time.

To me that sounds like what you really want is a singleton object with delegated methods.

Let's put together an example:

public interface ICurrencyWriter {
    string Write(int i);
    string Write(float f);
}

public class DelegatedCurrencyWriter : ICurrencyWriter {
    public DelegatedCurrencyWriter()
    {
        IntWriter = i => i.ToString();
        FloatWriter = f => f.ToString();
    }
    public string Write(int i) { return IntWriter(i); }
    public string Write(float f) { return FloatWriter(f); }
    public Func<int, string> IntWriter { get; set; }
    public Func<float, string> FloatWriter { get; set; }
}

public class SingletonCurrencyWriter {
    public static DelegatedCurrencyWriter Writer {
        get {
            if (_writer == null)
               _writer = new DelegatedCurrencyWriter();
            return _writer;
        }
    }
}

in use:

Console.WriteLine(SingletonCurrencyWriter.Writer.Write(400.0f); // 400.0

SingletonCurrencyWriter.Writer.FloatWriter = f => String.Format("{0} bucks and {1} little pennies.", (int)f, (int)(f * 100));

Console.WriteLine(SingletonCurrencyWriter.Writer.Write(400.0f); // 400 bucks and 0 little pennies

Given all this, we now have a singleton class that writes out currency values and I can change the behavior of it. I've basically defined the behavior convention at compile time and can now change the behavior at either compile time (in the constructor) or run time, which is, I believe the effect you're trying to get. If you want inheritance of behavior, you can do that to by implementing back chaining (ie, have the new method call the previous one).

That said, I don't especially recommend the example code above. For one, it isn't thread safe and there really isn't a lot in place to keep life sane. Global dependence on this kind of structure means global instability. This is one of the many ways that changeable behavior was implemented in the dim dark days of C: structs of function pointers, and in this case a single global struct.

Share:
21,941
Toto
Author by

Toto

C# developper

Updated on July 12, 2022

Comments

  • Toto
    Toto almost 2 years

    Why is static virtual impossible? Is C# dependent or just don't have any sense in the OO world?

    I know the concept has already been underlined but I did not find a simple answer to the previous question.

  • Hannoun Yassir
    Hannoun Yassir almost 15 years
    we don't call them functions :) we call them methods
  • Dykam
    Dykam almost 15 years
    You cannot do that, as static methods aren't inherited.
  • Lee Grissom
    Lee Grissom almost 12 years
    Delphi has had the concept of Virtual Class members (aka virtual statics) since the 1990's. Since Delphi was created by Anders Hejlsberg & Co back in the 1990's, it naturally begs the question of why he never introduced it (or something similar) into C#. Yes, it then complicates matters when discussing constructors, but I'm confident an elegant solution exists. +1 to OP
  • sbi
    sbi almost 12 years
    @Lee: Interesting, I didn't know that. Now, given that "static" means no object necessary, how do I invoke a static virtual function in Delphi? I can't even imagine how to do that.
  • Lee Grissom
    Lee Grissom almost 12 years
    @sbi, docwiki.embarcadero.com/RADStudio/en/… There are lots of valid scenarios, post a question on the Embarcadero forums to request some examples.
  • ivan_pozdeev
    ivan_pozdeev about 9 years
    This is actually called "Curiously recurring template pattern".
  • ivan_pozdeev
    ivan_pozdeev about 9 years
    This is no "bad choice of words", the definition for static - “determine the method to be called solely based on compile time static analysis” as per Michael Stum's answer - is what it actually meant ever since its introduction in C. The feature request is effectively to change its meaning to "class-bound".
  • Mikaël Mayer
    Mikaël Mayer about 9 years
    This name was invented by an engineer in 1995 minimum 6 years after F-bounded polymorphism was mathematically formalized. bit.ly/1Ft54Ah At the time, there were no internet though so I can't blame him for not looking at that (Google was founded in 1999)
  • ivan_pozdeev
    ivan_pozdeev about 9 years
    Wow, I didn't know that. Added this to the Wikipedia article.
  • ivan_pozdeev
    ivan_pozdeev about 9 years
    Extension methods are no different from plain virtual ones.
  • O. R. Mapper
    O. R. Mapper about 4 years
    Downvoted because this feature is actually supported in other OO languages, notably Delphi.
  • Daniel
    Daniel about 3 years
    Just applied Example 1 to my tool avoiding tons of boilerplate code. One small pitfall I came across was the call to the 'Create' method; this has to be called as A<T>.Create(0) or B<T>.Create(2); plain A.Create(0) or B.Create(2) is not working.