I've been working with providers a fair bit lately, and I came across an interesting situation where I wanted to have an abstract class that had an abstract static method. I read a few posts on the topic, and it sort of made sense, but is there a nice clear explanation?
-
4Please leave these open to allow to future improvements. – Mark Biek Sep 23 '08 at 17:49
-
1Possible duplicate of [How to implement virtual static properties?](https://stackoverflow.com/questions/15346631/how-to-implement-virtual-static-properties) – peterh Jan 10 '18 at 11:12
-
1As a side note, `TextWriter.Null` and `StreamWriter.Null` shown a similar attempt around this topic. – Ken Kin Jan 16 '18 at 04:41
-
2As pointed out in a newish answer this is now available for interfaces in the latest C#: https://stackoverflow.com/a/69666855/3195477 – StayOnTarget Mar 25 '22 at 12:13
-
1I don't understand a use case for abstract static methods? How are they going to be defined later since static methods have no inheritance? Is this another case for needing static method definitions in interfaces? – JAlex Mar 25 '22 at 12:54
-
1@JAlex you may find this interesting, it has plenty of examples & detailed discussion of the feature: https://github.com/dotnet/csharplang/issues/4436 – StayOnTarget Mar 25 '22 at 12:55
-
1@StayOnTarget - I would love to see static methods/operators in interfaces, especially for numeric types since operators _have to be static_. But in this case here I think we're talking about something different. – JAlex Mar 25 '22 at 13:00
-
1@JAlex the link above describes only abstract static methods/properties, not virtual (with a default implementation), maybe that's what you mean. There is a section there which talks about potentially doing that later. However they cite the operator cases as one of the specific motivations of the static abstract feature, maybe that's similar to what you are thinking. They give an IAddable example. – StayOnTarget Mar 25 '22 at 13:03
-
1@StayOnTarget - we'll see if it _ever_ gets implemented. There similar discussion going back to .NET 2.0 about this. – JAlex Mar 25 '22 at 15:47
10 Answers
Static methods are not instantiated as such, they're just available without an object reference.
A call to a static method is done through the class name, not through an object reference, and the Intermediate Language (IL) code to call it will call the abstract method through the name of the class that defined it, not necessarily the name of the class you used.
Let me show an example.
With the following code:
public class A
{
public static void Test()
{
}
}
public class B : A
{
}
If you call B.Test, like this:
class Program
{
static void Main(string[] args)
{
B.Test();
}
}
Then the actual code inside the Main method is as follows:
.entrypoint
.maxstack 8
L0000: nop
L0001: call void ConsoleApplication1.A::Test()
L0006: nop
L0007: ret
As you can see, the call is made to A.Test, because it was the A class that defined it, and not to B.Test, even though you can write the code that way.
If you had class types, like in Delphi, where you can make a variable referring to a type and not an object, you would have more use for virtual and thus abstract static methods (and also constructors), but they aren't available and thus static calls are non-virtual in .NET.
I realize that the IL designers could allow the code to be compiled to call B.Test, and resolve the call at runtime, but it still wouldn't be virtual, as you would still have to write some kind of class name there.
Virtual methods, and thus abstract ones, are only useful when you're using a variable which, at runtime, can contain many different types of objects, and you thus want to call the right method for the current object you have in the variable. With static methods you need to go through a class name anyway, so the exact method to call is known at compile time because it can't and won't change.
Thus, virtual/abstract static methods are not available in .NET.

- 1,398
- 1
- 16
- 33

- 380,855
- 102
- 628
- 825
-
5Combined with the way operator-overloading is done in C#, this unfortunately eliminates the possibility of requiring subclasses to provide an implementation for a given operator overload. – Chris Moschini Mar 20 '12 at 08:41
-
32I don't find this answer terribly useful as the definition of `Test()` is in `A` rather than being abstract and potentially defined in `B`.\ – May 31 '12 at 15:48
-
7Generic type parameters effectively behave as non-persistable "type" variables, and virtual static methods could be useful in such context. For example, if one had a `Car` type with a virtual static `CreateFromDescription` factory method, then code which accepted a `Car`-constrained generic type `T` could call `T.CreateFromDescription` to produce a car of type `T`. Such a construct could be supported pretty well within the CLR if each type which defined such a method held a static singleton instance of a nested class generic which held the virtual "static" methods. – supercat Jun 10 '13 at 22:27
-
`B.Test()` is wrong and the compiler should flag it. Use `A.Test()` since that is the class where the static method is defined under. – JAlex Mar 25 '22 at 12:51
Static methods cannot be inherited or overridden, and that is why they can't be abstract. Since static methods are defined on the type, not the instance, of a class, they must be called explicitly on that type. So when you want to call a method on a child class, you need to use its name to call it. This makes inheritance irrelevant.
Assume you could, for a moment, inherit static methods. Imagine this scenario:
public static class Base
{
public static virtual int GetNumber() { return 5; }
}
public static class Child1 : Base
{
public static override int GetNumber() { return 1; }
}
public static class Child2 : Base
{
public static override int GetNumber() { return 2; }
}
If you call Base.GetNumber(), which method would be called? Which value returned? It's pretty easy to see that without creating instances of objects, inheritance is rather hard. Abstract methods without inheritance are just methods that don't have a body, so can't be called.

- 16,507
- 9
- 88
- 138

- 10,061
- 5
- 39
- 43
-
49Given your scenario i would say Base.GetNumber() would return 5; Child1.GetNumber() returns 1; Child2.GetNumber() returns 2; Can you prove me wrong, to help me understand your reasoning? Thank you – Luis Filipe Oct 02 '08 at 16:30
-
The face that you think Base.GetNumber() returns 5, means that you already understand what is going on. By returning the base value, there is no inheritance going on. – David Wengier Oct 04 '08 at 22:54
-
78Why in the world would Base.GetNumber() return anything else but 5? It's a method in the base class - there's only 1 option there. – Artem Russakovskii Jun 17 '09 at 07:33
-
7@ArtemRussakovskii: Suppose one had `int DoSomething
() where T:Base {return T.GetNumber();}`. It would seem useful if `DoSomething – supercat Jun 16 '13 at 20:23()` could return five, while `DoSomething ()` would return two. Such ability would be not only useful for toy examples, but also for something like `class Car {public static virtual Car Build(PurchaseOrder PO);}`, where every class deriving from `Car` would have to define a method which could build an instance given a purchase order. -
6
-
7This is not a valid answer at all. As some others said, Base.GetNumber() must return 5 always. Child 1 & 2 must return 1 and 2 respectively. Nothing else makes sense. – Antonio Rodríguez Aug 24 '20 at 09:34
Another respondent (McDowell) said that polymorphism only works for object instances. That should be qualified; there are languages that do treat classes as instances of a "Class" or "Metaclass" type. These languages do support polymorphism for both instance and class (static) methods.
C#, like Java and C++ before it, is not such a language; the static
keyword is used explicitly to denote that the method is statically-bound rather than dynamic/virtual.

- 54,380
- 8
- 73
- 102
With .NET 6
/ C# 11/next/preview
you are able to do exactly that with "Static abstract members in interfaces".
(At the time of writing the code compiles successfully but some IDEs have problems highlighting the code)
using System;
namespace StaticAbstractTesting
{
public interface ISomeAbstractInterface
{
public abstract static string CallMe();
}
public class MyClassA : ISomeAbstractInterface
{
static string ISomeAbstractInterface.CallMe()
{
return "You called ClassA";
}
}
public class MyClassB : ISomeAbstractInterface
{
static string ISomeAbstractInterface.CallMe()
{
return "You called ClassB";
}
}
public class Program
{
public static void Main(string[] args)
{
UseStaticClassMethod<MyClassA>();
UseStaticClassMethod<MyClassB>();
}
public static void UseStaticClassMethod<T>() where T : ISomeAbstractInterface
{
Console.WriteLine($"{typeof(T).Name}.CallMe() result: {T.CallMe()}");
}
}
}
Since this is a major change in the runtime, the resulting IL code also looks really clean, which means that this is not just syntactic sugar.
public static void UseStaticClassMethodSimple<T>() where T : ISomeAbstractInterface {
IL_0000: constrained. !!T
IL_0006: call string StaticAbstractTesting.ISomeAbstractInterface::CallMe()
IL_000b: call void [System.Console]System.Console::WriteLine(string)
IL_0010: ret
}
Resources:
-
2And currently [planned for proper release in C#11](https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11). – ADBailey May 26 '22 at 15:48
This question is 12 years old but it still needs to be given a better answer. As few noted in the comments and contrarily to what all answers pretend it would certainly make sense to have static abstract methods in C#. As philosopher Daniel Dennett puts it, a failure of imagination is not an insight into necessity. It is a common mistake not to realize that C# is more than an OOP language. A pure OOP perspective on a given concept leads to a restricted - and in the current case misguided - examination. Polymorphism is not only about subtying polymorphism: it also includes parametric polymorphism (aka generic programming) and C# has been supporting this for a long time now. Within this additional paradigm, abstract classes (and most types) are not only used to provide a type to instances. They can also be used as bounds for generic parameters; something that has been understood by users of certain languages (like for example Haskell, but also more recently Scala, Rust or Swift) for years.
In this context you may want to do something like this:
void Catch<TAnimal>() where TAnimal : Animal
{
string scientificName = TAnimal.ScientificName; // abstract static property
Console.WriteLine($"Let's catch some {scientificName}");
…
}
And here the capacity to express static members that can be specialized by subclasses totally makes sense!
Unfortunately C# does not allow abstract static members but I'd like to propose a pattern that can emulate them reasonably well. This pattern is not perfect (it imposes some restrictions on inheritance) but as far as I can tell it is typesafe.
The main idea is to associate an abstract companion class (here SpeciesFor<TAnimal>
) to the one that should contain static abstract members (here Animal
):
public abstract class SpeciesFor<TAnimal> where TAnimal : Animal
{
public static SpeciesFor<TAnimal> Instance { get { … } }
// abstract "static" members
public abstract string ScientificName { get; }
…
}
public abstract class Animal { … }
Now we would like to make this work:
void Catch<TAnimal>() where TAnimal : Animal
{
string scientificName = SpeciesFor<TAnimal>.Instance.ScientificName;
Console.WriteLine($"Let's catch some {scientificName}");
…
}
Of course we have two problems to solve:
- How do we make sure an implementer of a subclass of
Animal
provides a specific instance ofSpeciesFor<TAnimal>
to this subclass? - How does the property
SpeciesFor<TAnimal>.Instance
retrieve this information?
Here is how we can solve 1:
public abstract class Animal<TSelf> where TSelf : Animal<TSelf>
{
private Animal(…) {}
public abstract class OfSpecies<TSpecies> : Animal<TSelf>
where TSpecies : SpeciesFor<TSelf>, new()
{
protected OfSpecies(…) : base(…) { }
}
…
}
By making the constructor of Animal<TSelf>
private we make sure that all its subclasses are also subclasses of inner class Animal<TSelf>.OfSpecies<TSpecies>
. So these subclasses must specify a TSpecies
type that has a new()
bound.
For 2 we can provide the following implementation:
public abstract class SpeciesFor<TAnimal> where TAnimal : Animal<TAnimal>
{
private static SpeciesFor<TAnimal> _instance;
public static SpeciesFor<TAnimal> Instance => _instance ??= MakeInstance();
private static SpeciesFor<TAnimal> MakeInstance()
{
Type t = typeof(TAnimal);
while (true)
{
if (t.IsConstructedGenericType
&& t.GetGenericTypeDefinition() == typeof(Animal<>.OfSpecies<>))
return (SpeciesFor<TAnimal>)Activator.CreateInstance(t.GenericTypeArguments[1]);
t = t.BaseType;
if (t == null)
throw new InvalidProgramException();
}
}
// abstract "static" members
public abstract string ScientificName { get; }
…
}
How do we know that the reflection code inside MakeInstance()
never throws? As we've already said, almost all classes within the hierarchy of Animal<TSelf>
are also subclasses of Animal<TSelf>.OfSpecies<TSpecies>
. So we know that for these classes a specific TSpecies
must be provided. This type is also necessarily constructible thanks to constraint : new()
. But this still leaves out abstract types like Animal<Something>
that have no associated species. Now we can convince ourself that the curiously recurring template pattern where TAnimal : Animal<TAnimal>
makes it impossible to write SpeciesFor<Animal<Something>>.Instance
as type Animal<Something>
is never a subtype of Animal<Animal<Something>>
.
Et voilà:
public class CatSpecies : SpeciesFor<Cat>
{
// overriden "static" members
public override string ScientificName => "Felis catus";
public override Cat CreateInVivoFromDnaTrappedInAmber() { … }
public override Cat Clone(Cat a) { … }
public override Cat Breed(Cat a1, Cat a2) { … }
}
public class Cat : Animal<Cat>.OfSpecies<CatSpecies>
{
// overriden members
public override string CuteName { get { … } }
}
public class DogSpecies : SpeciesFor<Dog>
{
// overriden "static" members
public override string ScientificName => "Canis lupus familiaris";
public override Dog CreateInVivoFromDnaTrappedInAmber() { … }
public override Dog Clone(Dog a) { … }
public override Dog Breed(Dog a1, Dog a2) { … }
}
public class Dog : Animal<Dog>.OfSpecies<DogSpecies>
{
// overriden members
public override string CuteName { get { … } }
}
public class Program
{
public static void Main()
{
ConductCrazyScientificExperimentsWith<Cat>();
ConductCrazyScientificExperimentsWith<Dog>();
ConductCrazyScientificExperimentsWith<Tyranosaurus>();
ConductCrazyScientificExperimentsWith<Wyvern>();
}
public static void ConductCrazyScientificExperimentsWith<TAnimal>()
where TAnimal : Animal<TAnimal>
{
// Look Ma! No animal instance polymorphism!
TAnimal a2039 = SpeciesFor<TAnimal>.Instance.CreateInVivoFromDnaTrappedInAmber();
TAnimal a2988 = SpeciesFor<TAnimal>.Instance.CreateInVivoFromDnaTrappedInAmber();
TAnimal a0400 = SpeciesFor<TAnimal>.Instance.Clone(a2988);
TAnimal a9477 = SpeciesFor<TAnimal>.Instance.Breed(a0400, a2039);
TAnimal a9404 = SpeciesFor<TAnimal>.Instance.Breed(a2988, a9477);
Console.WriteLine(
"The confederation of mad scientists is happy to announce the birth " +
$"of {a9404.CuteName}, our new {SpeciesFor<TAnimal>.Instance.ScientificName}.");
}
}
A limitation of this pattern is that it is not possible (as far as I can tell) to extend the class hierarchy in a satifying manner. For example we cannot introduce an intermediary Mammal
class associated to a MammalClass
companion. Another is that it does not work for static members in interfaces which would be more flexible than abstract classes.

- 305
- 2
- 10
Here is a situation where there is definitely a need for inheritance for static fields and methods:
abstract class Animal
{
protected static string[] legs;
static Animal() {
legs=new string[0];
}
public static void printLegs()
{
foreach (string leg in legs) {
print(leg);
}
}
}
class Human: Animal
{
static Human() {
legs=new string[] {"left leg", "right leg"};
}
}
class Dog: Animal
{
static Dog() {
legs=new string[] {"left foreleg", "right foreleg", "left hindleg", "right hindleg"};
}
}
public static void main() {
Dog.printLegs();
Human.printLegs();
}
//what is the output?
//does each subclass get its own copy of the array "legs"?

- 30,738
- 21
- 105
- 131

- 1,235
- 1
- 10
- 13
-
5No, there's only one instance of the array 'legs'. Output is nondeterministic as you don't know what order the static constructors will be called (there's actually no guarantee the base class static constructor would be called at all). 'Need' is a fairly absolute term where 'desire' is probably more accurate. – Sam Feb 18 '10 at 06:16
-
To add to the previous explanations, static method calls are bound to a specific method at compile-time, which rather rules out polymorphic behavior.

- 31,467
- 8
- 60
- 69
-
C# is statically typed; calls to polymorphic methods are also bound at compile time as I understand it - that is to say the CLR is not left to resolve which method to call during runtime. – Adam Tolley May 13 '11 at 21:23
-
1So how exactly do you think polymorphism works on the CLR? Your explanation just ruled out virtual method dispatch. – Rytmis May 14 '11 at 15:38
-
That's not really as useful a comment as it could be. I invited (with 'as I understand it') useful discourse, think maybe you could provide a little more content - seeing as people come here looking for answers and not insults. Although, it seems I may be guilty of the same thing - I really meant the above comment as a question: Doesn't C# evaluate these things at compile time? – Adam Tolley May 18 '11 at 18:17
-
1Apologies, I didn't mean an insult (although I do admit to responding a bit snappily ;-). The point of my question was, if you've got these classes: class Base { public virtual void Method(); } class Derived : Base { public override void Method(); } and write thusly: Base instance = new Derived(); instance.Method(); the compile-time type information on the call site is that we've got an instance of Base, when the actual instance is a Derived. So the compiler can't resolve the exact method to call. Instead it emits a "callvirt" IL instruction that tells the runtime to dispatch.. – Rytmis May 19 '11 at 13:40
-
... whereas for static methods, there's no instance to do virtual dispatch on, so it always necessarily emits a "call" instruction. And now that I expanded on my answer, I realize what a crappy answer it was. ;-) – Rytmis May 19 '11 at 13:42
-
1Thanks man, thats informative! Guess I have been putting off the dive into IL long enough, wish me luck. – Adam Tolley Jun 01 '11 at 15:44
We actually override static methods (in delphi), it's a bit ugly, but it works just fine for our needs.
We use it so the classes can have a list of their available objects without the class instance, for example, we have a method that looks like this:
class function AvailableObjects: string; override;
begin
Result := 'Object1, Object2';
end;
It's ugly but necessary, this way we can instantiate just what is needed, instead of having all the classes instantianted just to search for the available objects.
This was a simple example, but the application itself is a client-server application which has all the classes available in just one server, and multiple different clients which might not need everything the server has and will never need an object instance.
So this is much easier to maintain than having one different server application for each client.
Hope the example was clear.

- 5,914
- 11
- 61
- 77
The abstract methods are implicitly virtual. Abstract methods require an instance, but static methods do not have an instance. So, you can have a static method in an abstract class, it just cannot be static abstract (or abstract static).
-
2-1 virtual methods do not need an instance, except by design. And you do not actually address the question, so much as deflect it. – FallenAvatar Nov 09 '13 at 22:29