Why Can't I Have Abstract Static Methods in C#

Why can't I have abstract static methods in C#?

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.

C#, implement 'static abstract' like methods

Combining static and abstract is somewhat meaningless, yes. The idea behind static is one need not present an instance of the class in order to use the member in question; however with abstract, one expects an instance to be of a derived class that provides a concrete implementation.

I can see why you'd want this sort of combination, but the fact is the only effect would be to deny the implementation use of 'this' or any non-static members. That is, the parent class would dictate a restriction in the implementation of the derived class, even though there's no underlying difference between calling an abstract or 'static abstract' member (as both would need a concrete instance to figure out what implementation to use)

Can't define static methods in abstract types. How to work arround?

You can't have "virtual" static methods, as virtual/abstract/override suggests an instance being overridden at runtime.

You could do something like this, however:

public abstract class CmdBody
{
public static byte[] ToBytes<T>(T cmdBody) where T : CmdBody
{
return cmdBody.ToBytes();
}

protected abstract byte[] ToBytes();

public abstract int GetLength();
}

public class CmdBodyA : CmdBody
{
protected override byte[] ToBytes()
{ // Implementation }
}

public class CmdBodyB : CmdBody
{
protected override byte[] ToBytes()
{ // Implementation }
}

This allows each "CmdBody" type to define how it's serialized itself, but the base class static method to be the only publicly visible way to access it.

That being said, given your use case, there's no reason for making this static at all. You can just do:

public abstract class CmdBody
{
public abstract byte[] ToBytes();

public abstract int GetLength();
}

public class CmdBodyA : CmdBody
{
public override byte[] ToBytes()
{ // Implementation }
}

public class CmdBodyB : CmdBody
{
public override byte[] ToBytes()
{ // Implementation }
}


public class Cmd<T> where T : CmdBody
{
public CmdHeader Header { get; set; }
public T Body { get; set; }

public byte[] ToBytes()
{
byte[] cmdBytes = new byte[Header.GetLength() + Body.GetLength()];
Header.ToBytes().CopyTo(cmdBytes, 0);
Body.ToBytes().CopyTo(cmdBytes, Header.GetLength());

return cmdBytes;
}
}

Why can't static methods be abstract in Java?

The abstract annotation to a method indicates that the method MUST be overriden in a subclass.

In Java, a static member (method or field) cannot be overridden by subclasses (this is not necessarily true in other object oriented languages, see SmallTalk.) A static member may be hidden, but that is fundamentally different than overridden.

Since static members cannot be overriden in a subclass, the abstract annotation cannot be applied to them.

As an aside - other languages do support static inheritance, just like instance inheritance. From a syntax perspective, those languages usually require the class name to be included in the statement. For example, in Java, assuming you are writing code in ClassA, these are equivalent statements (if methodA() is a static method, and there is no instance method with the same signature):

ClassA.methodA();

and

methodA();

In SmallTalk, the class name is not optional, so the syntax is (note that SmallTalk does not use the . to separate the "subject" and the "verb", but instead uses it as the statemend terminator):

ClassA methodA.

Because the class name is always required, the correct "version" of the method can always be determined by traversing the class hierarchy. For what it's worth, I do occasionally miss static inheritance, and was bitten by the lack of static inheritance in Java when I first started with it. Additionally, SmallTalk is duck-typed (and thus doesn't support program-by-contract.) Thus, it has no abstract modifier for class members.

Why can an abstract class not be sealed or static?


  1. static class cannot be marked sealed because it is made sealed by compiler by default.

    Static classes are sealed and therefore cannot be inherited.

  2. static class cannot be marked as abstract, because it would be pointless. abstract class makes sense when you want all derived classes to implement same part of the logic. But because static class cannot be derived there is no way other class will implement these gaps.

    They cannot inherit from any class except Object.

Both quotes from Static Classes and Static Class Members (C# Programming Guide).

C# specification is a little more detailed about that:

10.1.1.3 Static classes

A static class may not include a sealed or abstract modifier. Note, however, that since a static class cannot be instantiated or derived from, it behaves as if it was both sealed and abstract.

You can read what does it mean for class to be sealed or abstract:

An abstract class cannot be instantiated directly, and it is a compile-time error to use the new operator on an abstract class

The sealed modifier is used to prevent derivation from a class. A compile-time error occurs if a sealed class is specified as the base class of another class.

Update

And a word about an article linked in the query you mentioned (Static Class Design). It's already stated in accepted answer from that question. If you read carefully you can see that:

DO declare static classes as sealed, abstract, and add a private instance constructor if your programming language does not have built-in support for static classes.

.NET (so C# as well) do have built-in support for static classes, so you don't have (and even can't) to make your classes pseudo-static by marking it both sealed and abstract.

Is the use of static methods in abstract classes new in C#?


Is the use of static methods in abstract classes new in C#?

No.

Why would relatively modern source code from Microsoft perpetuate such a practice?

Context is everything. In this case, it's obvious that CSharpSyntaxTree.ParseText is a factory method - it returns a new ParsedSyntaxTree instance (which is a private subclass of CSharpSyntaxTree). This is a perfectly valid use of a static method on an abstract class.

I'd even go further and disagree with the answer you linked. Abstract base classes are often simply for convenience, to reduce code duplication and capture some common behaviour from its subclasses. In this case, putting common static methods on it make sense.

Can't define static abstract string property

Static members do not have polymorphism, so they can't be abstract. :(

If that's what you need, consider making a Singleton object, and reading the property off that object.

Alternative to using static factory (as cannot have abstract static methods)

I would suggest a different solution. I would apply the Depdency Inversion Principle

Update with new Solution:

public class Datagram
{
public byte[] Data { get; set; }
}


public interface IPayload
{
Datagram Payload { get; }

}

public interface IConvertible
{
IPayload Convert(IPayload load);
}

public class EthernetDatagram : IPayload , IConvertible
{
public Datagram Payload
{
get
{
return null;
}
}


public IPayload Convert(IPayload load)
{
return new EthernetDatagram();
}
}

public class TcpDatagram : IConvertible, IPayload
{
public Datagram Payload
{
get
{
return null;
}
}

public IPayload Convert(IPayload load)
{
return null;
}
}

public static class Extension
{
public static IPayload As<T>(this IPayload load) where T : class, IConvertible, new()
{
IConvertible conv = new T();
return conv.Convert(load);
}
}

class Program
{
static void Main(string[] args)
{
IPayload load = new TcpDatagram();

var result = load.As<EthernetDatagram>();
}
}

With this solution you go the other way around. You leave the path of hard reflection and move it to different layer of abstraction by passing the concrete type you want to 'convert' to and have full control. All you have to do for new datagrams is to implement both interfaces as long as you wish a converting between them.
Is this more suitable for your problem?

Update to the comments:

The new solution will overcome the disadvantages of the former solution.
No reflection and specification of the 'converted' type by a generic parameter. You can chain calls to 'As' together to reach exactly what you want.
The only thing you now have to provide is the interface implementation, a default ctor and thats it.

C# call abstract method from static method

I did it!

lol, i implemented abstract static method in C# !

what did i:

  • created abstract class AbstractDbParameterConstructors, that don't contains any state, only abstract methods.
  • class ASqlWorker now gets generic, inhereted from AbstractDbParameterConstructors.

    public abstract partial class ASqlWorker<TPC>
    where TPC : AbstractDbParameterConstructors, new()
    { ... }
  • declared private static variable

    private static TPC generator = new TPC();

here both i have something like abstract static method, and i am protected from undesirable effects, from witch creators of standard were trying to protect me.

deatails : http://sourceforge.net/projects/sqlworker/

How to force abstract class childs to implement a static method?

A possible approach of combining a static behavior with inheritance or interface implementation is to use the singleton pattern. The access to a singleton object is static, but the object is created with new like a "normal" object

public interface ISomeInterface { ... }

public class SomeClass : ISomeInterface
{
public static readonly SomeClass Instance = new SomeClass();

private SomeClass()
{
}

// TODO: Implement ISomeInterface
// and/or override members from a base class.
}

Accessing a method of the singleton

ISomeInterface obj = SomeClass.Instance; // Static access to interface.
var y = obj.SomeMethod(x);


Related Topics



Leave a reply



Submit