7
class Test
{
    public BinaryWriter Content { get; private set; }
    public Test Write<T> (T data)
    {
        Content.Write(data);
        return this;
    }
}

it won't compile.

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'

it seems like Test.Write is always trying to call BinaryWriter.Write(bool). any suggestions?

Laie
  • 540
  • 5
  • 14
  • possible duplicate of [C# cannot call overloaded non-generic method from generic method](http://stackoverflow.com/questions/3905398/c-sharp-cannot-call-overloaded-non-generic-method-from-generic-method) – safetyOtter Mar 15 '14 at 06:59

5 Answers5

6

Overload resolution happens at compile-time, and in this case nothing is known about T, so no overload is applicable.

   class Test
    {
        public BinaryWriter Content { get; private set; }
        public Test Write<T>(T data)
        {
            Content.Write((dynamic)data);
            return this;
        }
    }

But of course it could make some problems. For example, appliction will compile fine, if you will send DateTime to the method. But, it will throw exception.

Farhad Jabiyev
  • 26,014
  • 8
  • 72
  • 98
2

This is possible but not with generic constraints . You can try to use Reflection and get the appropriate overloaded version of Write method according to type of T.

Initialize your BinaryWriter with a Stream in your constructor then use Reflection like below:

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;
    }
}

Here is a test program:

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
}
Selman Genç
  • 100,147
  • 13
  • 119
  • 184
1
  1. Using Reflection considerably slows down method calls. It also moves argument type check from compile time to runtime, which is undesirable in most cases.

  2. Using dynamic calls in this case is just a fancy and slightly optimized version of the previous method which has the same drawbacks.

  3. The correct way is to copy all overloads:

    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;
    }
    
    // ...
    

    This method is very verbose, but it is the only that provides compile-time checks of arument types and is the most performant as it chooses overloads and compile-time. Furthermore, these methods are likely to be inlined.

    In cases like this, I usually use a T4 script which generates code like above based on Reflection. Create a TT file, enumerate Write overloads of BinaryWriter, generate code.

Athari
  • 33,702
  • 16
  • 105
  • 146
0

In your write method T is generic, which means that T can be anything, but BinaryWriter.Write doesn't takes a generic overload. So you can't do that.

Sriram Sakthivel
  • 72,067
  • 7
  • 111
  • 189
0

You can't do that.

Since real type of T is unknown at compile-time, compiler can't find appropriate Write overload, and tries to call the first found one. There is no overload, which could be called with any type of T (e.g., Write(object)).

Dennis
  • 37,026
  • 10
  • 82
  • 150