Static interface equivalent C#

196 views Asked by At

I've worked with singletons in the past and I'm aware it's a solution for some people who are trying solve the static interface problem. In my case, I can't really use a singleton because I have an external class that I'm inheriting from and I have no control over this one (a library).

Basically, I have many classes inheriting from "TableRow" (the class in the library) and I need every single of these classes to implement a certain static method (ex: GetStaticIdentifier). Eventually, I need to store these objects in one of their base types, and use the static method on this specific type.

My question, is there another solution to this than using a singleton? Is there a feature I'm not aware of in C# that would help me solve this problem?

3

There are 3 answers

0
O. R. Mapper On BEST ANSWER

It seems you want to supply some meta-information along with the subclasses of TableRow; meta-information that can be retrieved without instantiating the particular subclass.

While .NET lacks static interfaces and static polymorphism, this can (to some extent, see below) be solved with custom attributes. In other words, you can define a custom attribute class that stores the information you want to associate with your type:

[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public class StaticIdentifierAttribute : Attribute
{
    public StaticIdentifierAttribute(int id)
    {
        this.staticIdentifier = id;
    }

    private readonly int staticIdentifier;

    public int StaticIdentifier {
        get {
            return staticIdentifier;
        }
    }
}

You can then apply this custom attribute to your TableRow subclasses:

[StaticIdentifier(42)]
public class MyTableRow : TableRow
{
    // ...
}

You can then retrieve the Type instance for MyTableRow (or any other subclass of TableRow) and use the GetCustomAttributes method to retrieve the StaticIdentifierAttribute instance and read out the value stored in itsStaticIdentifier` property for the class.

The drawback compared to static interfaces and static polymorphism is that it is not compile-time ensured that each TableRow subclass actually has that attribute; you will have to catch that (and either throw an exception, or ignore the respective TableRow subclass) at runtime.

Moreover, you cannot ensure that the attribute is only applied to TableRow subclasses, but then, while this may be a bit untidy, it doesn't really matter (if it is applied to another class, it will just not have any effect there, as no code ever processes it for other classes).

0
Rob On

If you twist yourself in knots, you can get a small amount of compiler checking. However, declaring a new struct type for every identifier instance you want is admittedly insane.

public interface IIdentifier
{
    int Id { get; }
}

public class BaseClass { }

public class ClassWithId<T> : BaseClass where T :  IIdentifier, new()
{
    public static int Id { get { return (new T()).Id; } }
}

public struct StaticId1 : IIdentifier
{
    public int Id { get { return 1; } }
}

public struct StaticId2 : IIdentifier
{
    public int Id { get { return 2; } }
}

//Testing
Console.WriteLine(ClassWithId<StaticId1>.Id);   //outputs 1
Console.WriteLine(ClassWithId<StaticId2>.Id);   //outputs 2
0
Fabjan On

How about using static class with generic(or not) extension methods ?

public static class Helper
{
  fields...

  public static void DoSomething<T>(this T obj)
  {
     do something...
  }
}