Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a workaround to use static methods by a generic class?

I have a rather simple problem, but there seems to be no solution within C#.

I have around 100 Foo classes where each implement a static FromBytes() method. There are also some generic classes which shall use these methods for its own FromBytes(). BUT the generic classes cannot use the static FromBytes() methods, because T.FromBytes(...) is illegal.

Do I miss something or is there no way to implement this functionality?

public class Foo1
{
    public static Foo1 FromBytes(byte[] bytes, ref int index)
    {
        // build Foo1 instance
        return new Foo1()
        {
            Property1 = bytes[index++],
            Property2 = bytes[index++],
            // [...]
            Property10 = bytes[index++]
        };
    }

    public int Property1 { get; set; }
    public int Property2 { get; set; }
    // [...]
    public int Property10 { get; set; }
}

//public class Foo2 { ... }
// [...]
//public class Foo100 { ... }

// Generic class which needs the static method of T to work
public class ListOfFoo<T> : System.Collections.Generic.List<T>
{
    public static ListOfFoo<T> FromBytes(byte[] bytes, ref int index)
    {
        var count = bytes[index++];
        var listOfFoo = new ListOfFoo<T>();
        for (var i = 0; i < count; i++)
        {
            listOfFoo.Add(T.FromBytes(bytes, ref index)); // T.FromBytes(...) is illegal
        }

        return listOfFoo;
    }
}

I think it would be unfair to choose an answer as accepted answer, after all answers and comments have contributed in different ways with their different views. It would be nice if someone writes a good overview about the different approaches with their pros and cons. That should be accepted after it helps future developers best.

like image 208
Karsten Gutjahr Avatar asked Nov 11 '13 13:11

Karsten Gutjahr


Video Answer


1 Answers

The best option would be to simply accept the specific FromBytes function as a delegate to your generic FromBytes function. This avoids both the performance cost and lack of compile time verifiability that comes along with using reflection.

public delegate T FromBytesFunc<T>(byte[] bytes, ref int index);
public static List<T> FromBytes<T>(byte[] bytes, ref int index,
    FromBytesFunc<T> function)
{
    var count = bytes[index++];
    var listOfFoo = new List<T>();
    for (var i = 0; i < count; i++)
    {
        listOfFoo.Add(function(bytes, ref index));
    }

    return listOfFoo;
}

Note that if you make the method, rather than the class it's in, generic, you can get the compiler to infer the generic argument. It could be called like so:

var list = SomeClass.FromBytes(bytes, ref index, Foo1.FromBytes);
like image 119
Servy Avatar answered Oct 31 '22 17:10

Servy