# Static Abstract in Practice

I recently encountered a problem where a class used a static method, and I had to provide a second implementation for this static method from one of the callsites. It looked like this case:

```csharp
public class MyClass
{
    public void Foo(int input)
    {
        var value = MyStaticType.Calculate(input);
        // ...
    }
}
```

I needed to have a different implementation for `Calculate` in one place I have been invoking the `Foo` method. There are multiple ways to address the issue, but I have chosen one that is only available on C# 11 and above.

## Alternative Solutions

First, let me elaborate on some of the alternative solutions. There are two alternative solutions that I discuss in this post.

One alternative solution could be to provide an extra `bool` or `enum` parameter to `Foo` method, which is then passed to `Calculate` method. `Calculate` method then can branch implementations based on the input. While this solution is straightforward, it involves an extra branching operation and passing the parameter. Eventually, we would end up with a second implementation of the `Calculate` method in the static `MyStaticType` type. However it might not belong to the same domain of `MyStaticType`, hence a new class could be necessary.

Another alternative could be converting `MyStaticType` to a non-static type and passing it as an input parameter of the `Foo` method (if someone does not prefer it as a method parameter, it could also be a type dependency of `MyClass`). `Foo` would not depend on `MyStaticType` directly, but it would need an input of a contract that is both implemented by `MyStaticType` and the alternative implementation (let us name it `MyAlternativeType`). This solution requires to create instances of either `MyStaticType` or `MyAlternativeType`. Depending on the situation someone might want to avoid this extra allocation.

## Using Static Abstract

A third solution could be abstracting the *static* class. In the past C# did not allow to create interfaces for static methods, but with C# 11 and [static abstract methods in interfaces](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-11.0/static-abstracts-in-interfaces) we can create a contract.

With this I could design a contract such as:

```csharp
public interface IMyContract
{
    public static abstract int Calculate(int input);
}
```

At this point both `MyStaticType` and `MyAlternativeType` can implement this interface. Unfortunately, they have to drop the `static` constraint in their type declaration:

```csharp
public class MyStaticType : IMyContract
{
    public static int Calculate(int input) => input + 1;
}

public class MyAlternativeType : IMyContract
{
    public static int Calculate(int input) => input - 1;
}
```

Method `Foo` can declare a generic type `T`, and constrain it to `IMyContract`:

```csharp
public class MyClass
{
    public void Foo<T>(int input) where T : IMyContract
    {
        var value = T.Calculate(input);
        // ...
```

Qt the call site of `Foo`, one can invoke it by passing the type as a generic type argument, that provides the *static* `Calculate` method: `c.Foo<MyStaticType>(1);`. This way we do not need to create a new instance for either of the implementations of `IMyContract` interface. Neither do we have to pass an extra parameter to the method - as the compiler will take care of passing this knowledge as a generic type parameter.

## Double Down Generics

One can push the idea further and double down on generics. Can we make the operation in `MyClass` generic too? One approach could be making the `Calculate` method generic, but applying any constraint on the static abstract method will be forced on the actual implementations too. However, we can make the interface generic such as:

```csharp
public interface IMyContract<T>
{
    public static abstract T Calculate(T input);
}
```

Derived types now can be generic, and even better, they may add different type constraints on the generic parameter:

```csharp
public class MyStaticType<T> : IMyContract<T> where T : IBinaryNumber<T>
{
    public static T Calculate(T input) => input + T.One;
}

public class MyAlternativeType<T> : IMyContract<T> where T : IBinaryInteger<T>
{
    public static T Calculate(T input) => input - T.One;
}
```

In this case `MyStaticType` requires that `T` to be an `IBinaryNumber<T>`, while `MyAlternativeType` requires it to be `IBinaryInteger<T>`. Please note, there is nothing specific to this implementation to require an `IBinaryInteger<T>`, it is purely for the sake of the example.

This allows us to generalize `Foo` method on the input type too:

```csharp
public class MyClass<T>
{
    public void Foo<U>(T input) where U : IMyContract<T>
    {
        var value = U.Calculate(input);
        // ...
```

Instead of adding the generic type parameter on the method, it is again added to the class definition of `MyClass`. Notice `Foo` still has a generic type parameter `U`, which has a constraint to be `IMyContract<T>`. Notice, `Foo` method, has no constraints on the type `T`, all the constraints on it will come due to the constraints depending on the actual implementation of `IMyContract`.

For example, this setup allows to invoke `Foo` with `MyStaticType` or `MyAlternativeType` with integer type parameters, such as `short` or `int`:


```csharp
var example0 = new MyClass<short>();
example0.Foo<MyAlternativeType<short>>(1);

var example1 = new MyClass<int>();
example1.Foo<MyAlternativeType<int>>(1);

var example2 = new MyClass<short>();
example2.Foo<MyStaticType<short>>(1);

var example3 = new MyClass<int>();
example3.Foo<MyStaticType<int>>(1);
```

While `MyStaticType` allows non-integer types like `double`, `MyAlternativeType` does not. As shown below the compiler enforces this constraint, and while *example4* compiles, *example5* will result a compiler error:

 **CS0315 The type 'double' cannot be used as type parameter 'T' in the generic type or method 'MyAlternativeType<T>'. There is no boxing conversion from 'double' to 'System.Numerics.IBinaryInteger<double>'.**

```csharp
var example4 = new MyClass<double>();
example4.Foo<MyStaticType<double>>(1);

var example5 = new MyClass<double>();
example5.Foo<MyAlternativeType<double>>(1); // Compiler error
```

## Conclusion

Previously I found *static abstract* methods a bit impractical for line of business applications. However, this example shows that they can come in very handy when we need to *abstract* static methods (no pun intended), while avoiding the alternatives described above. Combining it with regular generic types and constraints, a developer may define a strong control over how types may be composed, while keeping the implementation generic.