C# 在泛型方法中调用重载方法

C# 在泛型方法中调用重载方法,c#,C#,看起来Test.Write总是试图调用BinaryWriter.Write(bool)。有什么建议吗?重载解析发生在编译时,在这种情况下,对T一无所知,因此不适用重载 1. The best overloaded method match for 'System.IO.BinaryWriter.Write(bool)' has some invalid arguments 2. Argument 1: cannot convert from 'T' to 'bool' 类测试 { 公共二进制编

看起来Test.Write总是试图调用BinaryWriter.Write(bool)。有什么建议吗?

重载解析发生在编译时,在这种情况下,对T一无所知,因此不适用重载

1. The best overloaded method match for 'System.IO.BinaryWriter.Write(bool)' has some invalid arguments
2. Argument 1: cannot convert from 'T' to 'bool'
类测试
{
公共二进制编写器内容{get;private set;}
公共测试写入(T数据)
{
内容。写入((动态)数据);
归还这个;
}
}

当然,这也会带来一些问题。例如,如果您将DateTime发送给该方法,则appliction将很好地编译。但是,它会抛出异常。

在您的写入方法中,
T
是泛型的,这意味着
T
可以是任何东西,但
BinaryWriter.write
不接受泛型重载。所以你不能那样做。

你不能那样做


由于
T
的实际类型在编译时未知,编译器无法找到合适的
Write
重载,并尝试调用第一个找到的重载。没有重载,可以使用任何类型的
T
(例如,
Write(object)
)调用重载。

这是可能的,但不能使用一般约束。您可以尝试使用反射,并根据
T
的类型获得适当的
Write
方法重载版本

使用构造函数中的
初始化您的
BinaryWriter
,然后使用反射,如下所示:

   class Test
    {
        public BinaryWriter Content { get; private set; }
        public Test Write<T>(T data)
        {
            Content.Write((dynamic)data);
            return this;
        }
    }
  • 使用反射会大大降低方法调用的速度。它还将参数类型检查从编译时移动到运行时,这在大多数情况下是不可取的

  • 在这种情况下,使用动态调用只是前一种方法的一个花哨的稍微优化的版本,它也有同样的缺点

  • 正确的方法是复制所有重载:

    Test writer;
    using (var fs = new FileStream("sample.txt", FileMode.Open))
    {
         writer = new Test(fs);
         writer = writer.Write(232323);
         writer = writer.Write(true);
         writer = writer.Write(12);
    }
    
    using (var fs = File.Open("sample.txt", FileMode.Open))
    {
        var reader = new BinaryReader(fs);
        Console.WriteLine(reader.ReadInt32());  // 232323
        Console.WriteLine(reader.ReadBoolean()); // true
        Console.WriteLine(reader.ReadByte());    // 12
    }
    
    这个方法非常冗长,但它是唯一一个提供Arment类型编译时检查的方法,而且在选择重载和编译时时时性能最好。此外,这些方法可能是内联的

    在这种情况下,我通常使用T4脚本,该脚本基于反射生成上述代码。创建一个TT文件,枚举
    二进制编写器的
    重载,生成代码


  • 也许它可以解决问题,但这种方法很危险,而且容易出现异常。实际上,在这种情况下,它不需要是泛型方法。最烦人的是,我永远看不到
    -1
    的解释。
    class Test
    {
        public BinaryWriter Content { get; private set; }
    
        public Test(Stream stream)
        {
            Content = new BinaryWriter(stream);
        }
    
        public Test Write<T>(T data)
        {
    
            var method = typeof (BinaryWriter).GetMethod("Write", new[] {data.GetType()});
            if (method != null)
            {
                method.Invoke(Content, new object[] { data });
            }
            // here you might want to throw an exception if method is not found
    
            return this;
        }
    }
    
    Test writer;
    using (var fs = new FileStream("sample.txt", FileMode.Open))
    {
         writer = new Test(fs);
         writer = writer.Write(232323);
         writer = writer.Write(true);
         writer = writer.Write(12);
    }
    
    using (var fs = File.Open("sample.txt", FileMode.Open))
    {
        var reader = new BinaryReader(fs);
        Console.WriteLine(reader.ReadInt32());  // 232323
        Console.WriteLine(reader.ReadBoolean()); // true
        Console.WriteLine(reader.ReadByte());    // 12
    }
    
    public Test Write (bool data)
    {
        Content.Write(data);
        return this;
    }
    
    public Test Write (byte data)
    {
        Content.Write(data);
        return this;
    }
    
    public Test Write (byte[] data)
    {
        Content.Write(data);
        return this;
    }
    
    public Test Write (char data)
    {
        Content.Write(data);
        return this;
    }
    
    public Test Write (char[] data)
    {
        Content.Write(data);
        return this;
    }
    
    // ...