Why can't interfaces specify static methods? - c#

I know this question has been asked over and over, but I can't seem to find good enough answers. So to make it clear what I'm trying to know, I'll split this in two questions:
Why can't interfaces have static method signatures? I'll try to preempt the non-answers asking why in the world I would want to do this with the following: I would want to be able to statically invoke GetDbConnectionType() on SqliteCodeGenerator and MssqlCodeGenerator:
interface ICodeGenerator
{
// this is the method I would like to be static:
string GetDbConnectionType();
}
abstract class CodeGeneratorBase : ICodeGenerator
{
public abstract string GetDbConnectionType();
public void GenerateSomeCode(StringBuilder s)
{
s.AppendLine("var foo = new " + GetDbConnectionType() + "();");
}
}
class SqliteCodeGenerator : CodeGeneratorBase
{
public override string GetDbConnectionType()
{
return "SQLiteConnection";
}
}
class MssqlCodeGenerator : CodeGeneratorBase
{
public override string GetDbConnectionType()
{
return "SqlConnection";
}
}
On the other hand, and this is the matter of this second question, if you know of a good alternative to reach the aforementioned goal, then by all means...

Suppose you could specify in an interface that a type had to have a particular static method... how would you call it? Polymorphism works through instances - whereas static members explicitly don't use instances.
Now, having said that, there's one situation in which I can see static interface members working: generic types. For example:
// This isn't valid code...
public void Foo<T>() where T : ICodeGenerator
{
string type = T.GetDbConnectionType();
}
That would call the static member on the concrete type T.
I've blogged more about this, but I suspect the benefit doesn't justify the complexity.
In terms of alternatives - usually you'd have another interface, and have separate types to implement that interface. That works well in some contexts, but not in others.

#JonSkeet: It's possible to create a static interface member in CIL, so I'm afraid your first statement is misleading. I assume it was omitted from C# as a design choice by the Microsoft team to encourage correct usage of interfaces.
The best way to get this functionality is probably with extension methods, these will allow you to add a method to all inheritors of your interface or to a specific implementation of that interface however you need to write a separate class to hold the implementation of the extension method which (if not planned for) can be easy to lose track of.

Jon's answer covers pretty much everything so my answer only includes a possible work around using the .NET configuration API. It requires a bit of syntax overhead but it does give you static access to the instance.
interface IStorage
{
void Store(string item);
}
static class Storage
{
private static readonly IStorage _instance;
static Storage()
{
var storageTypeString = ConfigurationManager.AppSettings["storageTypeString"];
var storageType = Type.GetType(storageTypeString, true);
_instance = (IStorage)Activator.CreateInstance(storageType);
}
public static void Store(string item)
{
_instance.Store(item);
}
}

It might be somewhat helpful if an interface could specify a static class, such that members of that class would be seen by the compiler as static members of that interface. Thus, instead of having to use static class Enumerable<T> to get Enumerable<T>.Default, one could instead syntactically specify IEnumerable<T>.Default.
It would be even more helpful if an interface could specify that some such static methods should be usable in a fashion similar to extension methods, but without the weird scoping rules associated with them (so an interface could appear to offer multiple "convenience" overloads for some member functions without requiring all of the implementations to provide them).
It would be extremely helpful if, combined with such a feature, interface methods could be declared "optional", such that when an implementation provided a method it would be used, and when it did not the extension-ish method would be automatically substituted. This would probably require changes to the CLR, however.
In any case, because interfaces do not include static classes, the best one can do is provide static classes which users of the interface will find helpful, even though the compiler will regard those classes and the interfaces as entirely independent entities.

I know this is old, but actually you can with static functions declared in a static class outside of a name space.
but they way your putting it you would just make the function static in the abstract class
to do it from an interface you do this
public static class Interfacefunction{
public static string GetDbConnectionType(this ICodeGenerator me)
{
// this is the method I would like to be static:
// you can even get access to me
return "SQLiteConnection";
}
}

A sort of workaround (though it may actually be better this way) for this I've decided to use is to use a static instance instead of a static interface.
Rather than:
// does not compile
ISomeInterface {
static void DoSomething();
static bool TestSomething(string pValue);
// etc...
}
static class SomeStaticClass : ISomeInterface {
public static void DoSomething() {
}
public static bool TestSomething(string pValue) {
}
}
Define a class (make it generic if the logic must vary between classes that you use it with):
sealed class SomeClass {
public void DoSomething() {
// reusable implementation
}
public bool TestSomething(string pValue) {
// reusable implementation
}
}
and give a static instance of that class to your static class:
static class SomeStaticClass {
static readonly SomeClass sSomeClass = new SomeClass();
}
The only issue is that you have to decide whether to expose a property to the static instance:
static class SomeStaticClass {
static readonly SomeClass sSomeClass = new SomeClass();
public static SomeClass SomeProperty { get { return sSomeClass; } }
}
...
SomeStaticClass.SomeProperty.DoSomething();
if (SomeStaticClass.SomeProperty.TestSomething(someValue))
...
or to wrap its methods:
static class SomeStaticClass {
static readonly SomeClass sSomeClass = new SomeClass();
public static void DoSomething() {
sSomeClass.DoSomething();
}
public static bool TestSomething(string pValue) {
sSomeClass.TestSomething(pValue);
}
}
...
SomeStaticClass.DoSomething();
if (SomeStaticClass.TestSomething(someValue))
...

Related

Alternative to traits

I'm quite new to C# coming from PHP and I have encountered a problem for which traits would be perfect but I understand that C# doesn't support traits. What is the best way to solve this?
In Godot I'd like to make the animation a bit easier on myself by adding a few methods for animation, according to PHP I'd do something like this. The methods can't really be static either.
public trait SpriteAnimator {
public void Animate(string animation)
{
// DO SOMETHING
}
}
public class Actor : KinematicBody2D
{
use SpriteAnimator;
public override void _Ready()
{
Animate("run");
}
}
How would I solve this in C#?
C# does not have anything that is completely analogous to PHP's trait system but some aspects of it can be emulated using interfaces, Extension Methods and occasionally Default Interface Methods.
The simplest usage of trait is to add methods to classes without subclassing. Extension methods allow you to effectively add methods to objects based on their type. Only members that are publicly visible on the targetted type will be accessible in the extension.
public interface INamed
{
string Name { get; }
}
public static class DemoExtensions
{
// This is available on instances of any type
public static void SayHello(this object self)
{
Console.WriteLine("Hello.")
}
// This one will work on instances whose type implements INamed
public static void SayHello(this INamed self)
{
Console.WriteLine($"Hello {self.Name}.");
}
}
Static trait data members are more difficult. While you can define a static field or property in the extension class (DemoExtensions above) the value is shared among all types that the extension method runs on. If you need static values based on the type of object the method is called against then you'll need to handle that manually with a Dictionary<type, ...> static in the extension class.
Another limitation is that extension methods require an object to invoke:
public class MyClass : INamed
{
public string Name { get; }
public MyClass(string name)
{
Name = name;
}
public void DoSomething()
{
this.SayHello();
}
}
Note the this.SayHello(); line in DoSomething. If you take the this. portion away the program will not compile.
Default Interface Methods can also be used as a sort of extension, but you have to force cast the type to the interface before you can access them. No more this.SayHello();, now it's ((INamed)this).SayHello(); and that's not even the worst of it. They have their place but mostly it's not useful to me. Your milage may vary.
As of C#9 there is no way to add extension types other than methods, and I very strongly doubt that we'll get Extension Properties at any point in the future. You'll have to figure your own way around trait properties until that changes.

public static method + interface

Since we can't define a public static method in the interface, can such an interface be implemented in a class with public static?
public interface IValidator
{
bool IsValid(bool data);
}
public class MyValidator : IValidator
{
public static bool IsValid(string data)
{
//code which returns bool
}
}
No, C# does not allow for static interfaces.
Interfaces are designed to act as contracts between classes, that contract defines that each instance of these classes will have a set of method.
Jon Skeet has given a very good explanation in this question, I'd recommend reading it.
When you have an object instance, it makes sense to cast and use that as an interface. But when you work with static stuff, this isn't the case. You can only access static members through the name of the containing class, you can't pass them around like instances, etc.
It is possible to implement an interface and make sure it's not instantiated multiple times, it's called the singleton pattern. A singleton class is similar to a static class, but it has an instance that can be passed around and it can implement interfaces as well.
No, but you could get something close to it by having a static member return an instance of the interface.
Somthing like:
public class MyValidator : IValidator
{
public bool IsValid(string data)
{
//code which returns bool
}
public static readonly IValidator Instance = new MyValidator();
}
Then you could use it in a static sort of way:
bool isValid = MyValidator.Instance.IsValid("data");
You cannot define static members via the interface, so if static members are required by design they can only be added to concrete types.
This ultimately produces a lot of confusion. Any other implementation would not have that same member. Mocked instances will not have access to that member. And so on.
Solution is to avoid declaring static members. In your particular case, I would object to the very design of the interface. I would prefer to see classes implement some interface like IValidatable:
public interface IValidatable
{
bool IsValid();
}
...
public class SomeBoolClass: IValidatable
{
private bool Data;
public bool IsValid()
{
return this.Data; // i.e. return Data == true
}
}
...
public class SomeStringClass: IValidatable
{
private string Data;
public bool IsValid()
{
return !string.IsNullOrEmpty(this.Data);
}
}
In this way you obtain fully polymorphic validation across all current and future types.
If you insist on having a validator which receives low-level data (such as Boolean or string) to validate, then you are half-way doomed. Suppose that there are two classes which wrap string data. These two classes would normally have to be validated in different ways. But validator would not be able to distinguish which validation algorithm to apply based on input data. Even worse, validator would have to contain all validation logic for all types, existing and those yet to be coded. This means that validator would act as one giant (and inherently incomplete) switch statement.

C# interface static method call with generics

Is there a simple way to implement this, and if possible without instanciating an object :
interface I
{
static string GetClassName();
}
public class Helper
{
static void PrintClassName<T>() where T : I
{
Console.WriteLine(T.GetClassName());
}
}
Try an extension method instead:
public interface IMyInterface
{
string GetClassName();
}
public static class IMyInterfaceExtensions
{
public static void PrintClassName<T>( this T input )
where T : IMyInterface
{
Console.WriteLine(input.GetClassName());
}
}
This allows you to add static extension/utility method, but you still need an instance of your IMyInterface implementation.
You can't have interfaces for static methods because it wouldn't make sense, they're utility methods without an instance and hence they don't really have a type.
You can not inherit static methods. Your code wouldn't compile in any way, because a interface can't have static methods because of this.
As quoted from littleguru:
Inheritance in .NET works only on
instance base. Static methods are
defined on the type level not on the
instance level. That is why overriding
doesn't work with static
methods/properties/events...
Static methods are only held once in
memory. There is no virtual table etc.
that is created for them.
If you invoke an instance method in
.NET, you always give it the current
instance. This is hidden by the .NET
runtime, but it happens. Each instance
method has as first argument a pointer
(reference) to the object that the
method is run on. This doesn't happen
with static methods (as they are
defined on type level). How should
the compiler decide to select the
method to invoke?
I also tried to setup a static method on an interface a little while ago, not sure why now. I did bookmark this so maybe it helps:
Interface with a static method by using extension methods
If you're just after the type name, you can just do this:
public class Helper
{
static void PrintClassName<T>()
{
Console.WriteLine(typeof(T).Name);
}
}
Declaring a static property, event or method on an interface definition is not considered a legal definition. This is because interfaces are considered contracts and as such, represent something that will be implemented by every client instance of that interface.
A static declaration essentially states that the static member does not require a physical client implementation in order to execute the required functionality and this falls short of the general concept of interfaces: providing a proven contract.
The answer is a qualified "not really but Sort Of". You can provide a static extension method to all implementors of a given interface and can then call this from your implementer in a property or another method. As an example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace InterfacesWithGenerics
{
class Program
{
static void Main(string[] args)
{
Helper.PrintClassName<Example>(new Example());
Console.ReadLine();
}
}
public class Example : I
{
#region I Members
public string ClassName
{
get { return this.GetClassName(); }
}
#endregion
}
public interface I
{
string ClassName { get; }
}
public class Helper
{
public static void PrintClassName<T>(T input) where T : I
{
Console.WriteLine( input.GetClassName()) ;
}
}
public static class IExtensions
{
public static string GetClassName(this I yourInterface)
{
return yourInterface.GetType().ToString();
}
}
}
Here we have an interface (I) which defines the property we care about and a static extension method (GetClassName) which is applied to all members of its type which does the grunt work of getting the information we want. We Have a Class (Example) which implements the I interface so when we call our static helper class passing in an instance of Example, it runs the static method against it. Unfortunately it is not valid to reference the type T directly within the method itself as a variable, you'll have to pass an instance into the application.
You could define the className as attribute on the specific class. This is the preferred ay to store metadata in .net. This way you can query the attribute for the given class and you do not need an instance.
Yes, you can - sort-of - if you don't mind defining new types that proxy instance calls to static methods:
While an interface can only declare instance members, you can use a couple of simple tricks with C#'s generics, without needing reflection, to accomplish what you're after (and without resorting to Java-style AbstractFactoryBeanFactory design-pattern overuse).
What we can do, is define a separate struct (i.e. a value-type) that contains instance members that call-into the static members we want.
So if we have this interface:
interface IStaticFunctionality
{
void DoSomethingWithoutAnObjectInstance();
}
...and we want to do something like this:
void AGenericMethodThatDoesntHaveAnInstanceOfT<T>()
{
T.DoSomethingWithoutAnObjectInstance();
}
...then we can do this:
void AGenericMethodThatDoesntHaveAnInstanceOfT<T>()
where T : struct, IStaticFunctionality
{
T t = default;
t.DoSomethingWithoutAnObjectInstance();
// Note the above code uses `T t default;` instead of `T t = new T()`.
// This is because the C# compiler currently replaces `new T()` with `Activator.CreateInstance<T>()` in the generated bytecode.
// This has poor performance compared to `default(T)` or a normal non-generic constructor call, but the compiler does this because it's a workaround for a design-bug back in C# 6.0: https://devblogs.microsoft.com/premier-developer/dissecting-the-new-constraint-in-c-a-perfect-example-of-a-leaky-abstraction/
}
So if we have different types with the static void DoSomethingWithoutAnObjectInstance method, we just need to define struct implementations of IStaticFunctionality for each of those types:
class Foo
{
public static void DoSomethingWithoutAnObjectInstance()
{
Console.WriteLine("foo");
}
struct Static : IStaticFunctionality
{
void DoSomethingWithoutAnObjectInstance() => Foo.DoSomethingWithoutAnObjectInstance();
}
}
class Bar
{
public static void DoSomethingWithoutAnObjectInstance()
{
Console.WriteLine("bar");
}
struct Static : IStaticFunctionality
{
void DoSomethingWithoutAnObjectInstance() => Bar.DoSomethingWithoutAnObjectInstance();
}
}
So then a call-site for AGenericMethodThatDoesntHaveAnInstanceOfT<Foo> would actually look like:
AGenericMethodThatDoesntHaveAnInstanceOfT<Foo.Static>();

Static Class Vs. Class with private constructor and all static properties and methods?

When I create utility classes I typically create a class that has a private constructor and exposes all of it's methods and properties as static. What's the best approach for this? What's the difference between the way I do or creating a static class?
Static classes are automatically sealed, so people can't inherit and override their behavior.
That is the only real difference (unless there is something special in the IL)
So if you use a static class, you save yourself the trouble of making the constructor private, and declaring the class sealed.
I would add, that defining a class as static, is "self-documenting" code. Users of your library will know that this class should not be instantiated, and only has static values.
A static class can never be instantiated. No way, no how.
A non-static class with a private constructor but all static methods can be abused in various ways - inheritance, reflection, call the private constructor in a static factory - to instantiate the class.
If you never want instantiation, I'd go with the static class.
Edit - Clarification for FosterZ's comment
Say you have this utility class:
public class Utility
{
public static string Config1 { get { return "Fourty Two"; } }
public static int Negate(int x) { return -x; }
private Utility() { }
}
If another developer isn't clear on its intent, they could do this:
public class Utility
{
public static string Config1 { get { return "Fourty Two"; } }
public int Config2 { get; set; }
public static int Negate(int x) { return -x; }
private Utility() { }
/// Get an instance of Utility
public static Utility GetUtility()
{
return new Utility();
}
}
Now you have a Frankenstein class. Some of its features require instantiation and some don't. Maybe that's what you want but maybe it's not. You could prevent this with code review, but why not make your intentions explicit in code? Marking the class as static eliminates any possible confusion. You can't instantiate a static class or inherit from it.
In addition to the previous answers: The compiler won't allow non-static members on static classes and produces and error. This may help a little bit to not accidently add non-static members.
you can pass object of a class that has private constructor as a parameter to any method but you can't do the same with static class. This is the major difference.
Also I'm going to go with the private constructor never being called by the static methods. So any initialisation in there would be wasted... But that's just a theory.

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

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?
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.
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.
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.
With .NET 6 / C# 10/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)
SharpLab Demo
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:
https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/6.0/static-abstract-interface-methods
https://github.com/dotnet/csharplang/issues/4436
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"?
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 put it, a failure of imagination is not an insight into necessity. There is a common mistake in not realizing that C# is not only 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 of SpeciesFor<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.
To add to the previous explanations, static method calls are bound to a specific method at compile-time, which rather rules out polymorphic behavior.
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.
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).
It's available in C# 10 as a preview feature for now.

Categories