是否有通用类使用静态方法的解决方法?

Kar*_*ahr 8 c# generics reflection

我有一个相当简单的问题,但在C#中似乎没有解决方案.

我有大约100个Foo类,每个类都实现一个static FromBytes()方法.还有一些泛型类应该使用这些方法FromBytes().但是泛型类不能使用这些static FromBytes()方法,因为它们T.FromBytes(...)是非法的.

我是否遗漏了某些内容或者无法实现此功能?

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我认为,在所有答案和评论以不同的方式对不同的观点做出贡献后,选择答案作为公认的答案是不公平的.如果有人用不同的方法对不同的方法进行了很好的概述,那就太好了.在它帮助未来的开发人员最好之后,应该接受它.

Ser*_*rvy 5

最好的选择是简单地接受特定FromBytes函数作为泛型FromBytes函数的委托.这避免了使用反射时出现的性能成本和编译时可验证性.

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;
}
Run Code Online (Sandbox Code Playgroud)

请注意,如果您创建方法而不是它所使用的类,那么您可以让编译器推断泛型参数.它可以像这样调用:

var list = SomeClass.FromBytes(bytes, ref index, Foo1.FromBytes);
Run Code Online (Sandbox Code Playgroud)


Kar*_*ahr 0

这将是所有未来观众的摘要。

由于您不能只调用该方法,因此主要问题是获取委托。有两种方法:

  • 通过反射
  • 来自呼叫者

您可能认为反射很慢,但性能不是问题。如果委托存储在静态字段中,则每个类只需执行一次,因为泛型类型不共享静态成员。

编译时可验证性是一个问题。如果您非常关心编译时可验证性,您应该从调用者传递委托。如果您更关心干净的方法调用,则必须牺牲编译时可验证性。

PS:有些人建议使用字典或 switch/case 或 if/else 来存储代表。这是你不应该做的事情。这与将委托存储在泛型类的静态字段中没有任何优势(泛型类型不共享静态成员)。