我无法弄清楚为什么以下代码返回Cannot resolve method Write(T)
- 这对我来说似乎毫不含糊:
private static void WriteToDisk<T>(string fileName, T[] vector) { using (var stream = new FileStream(fileName, FileMode.Create)) { using (var writer = new BinaryWriter(stream)) { foreach(T v in vector) writer.Write(v); writer.Close(); } } }
我想定义一个通用的二进制写方法,它可以处理例如int[]
,long[]
或double[]
的向量。
答案 0 :(得分:10)
要调用的Write()
的重载将在编译时确定,而不是在运行时。 BinaryWriter
需要Write(object)
重载(或Write<T>(T)
泛型重载)才能允许以这种方式调用方法。此错误(正确)表示它没有。
您需要编写自己的包装器方法,该方法接受object
(或通用类型的参数)并检查其类型以确定要调用的BinaryWriter.Write()
重载。
答案 1 :(得分:3)
cdhowie有正确的解释。重载解析在编译时发生,在这种情况下,对T
一无所知,因此不适用过载。
使用dynamic
,重载解析会在运行时发生。也许你可以使用:
writer.Write((dynamic)v)
由于拳击和重复的重载分辨率发生在运行时,它会有点慢。
修改:如果由于某种原因您无法访问dynamic
,则可以通过显式反射获得类似的行为:
private static void WriteToDisk<T>(string fileName, T[] vector)
{
var correctMethod = typeof(BinaryWriter).GetMethod("Write", new[] { typeof(T), });
if (correctMethod == null)
throw new ArgumentException("No suitable overload found for type " + typeof(T), "T");
using (var stream = new FileStream(fileName, FileMode.Create))
{
using (var writer = new BinaryWriter(stream))
{
foreach(var v in vector)
correctMethod.Invoke(writer, new object[] { v, });
}
}
}
我不知道这是否比dynamic
更快或更慢。
在任何一种情况下,如果您不小心使用T
不支持的DateTime
类型(例如BinaryWriter
),一切都会正常编译,您只会发现错误在运行时(代码运行时)。请参阅jam40jeff的答案,了解更加类型安全的解决方案,您可以通过将委托实例传递给方法来自行指定过载。
答案 2 :(得分:3)
我不同意dynamic
是最好的方法。这里的问题是你需要保证调用者传递T
可以处理的类型BinaryWriter.Write()
。由于没有可以通过约束T
来保证这一点的公共类或接口,因此最好的方法是将“传递降压”传递给调用者,如下所示:
private static void WriteToDisk<T>(string fileName, T[] vector, Action<BinaryWriter, T> callWrite)
{
using (var stream = new FileStream(fileName, FileMode.Create))
{
using (var writer = new BinaryWriter(stream))
{
foreach (T v in vector)
callWrite(writer, v);
writer.Close();
}
}
}
这称为如下:
WriteToDisk("filename", new int[0], (w, o) => w.Write(o)); // compiles
WriteToDisk("filename", new string[0], (w, o) => w.Write(o)); // compiles
WriteToDisk("filename", new DateTime[0], (w, o) => w.Write(o)); // doesn't compile (as desired)
当然,如果只有一小部分已知类型,您可以创建“便利方法”:
private static void WriteToDisk(string fileName, int[] vector)
{
WriteToDisk(fileName, vector, (w, o) => w.Write(o));
}
private static void WriteToDisk(string fileName, string[] vector)
{
WriteToDisk(fileName, vector, (w, o) => w.Write(o));
}
现在你的电话只是:
WriteToDisk("filename", new int[0]);
WriteToDisk("filename", new string[0]);
更多代码,但更多的编译时类型安全性和速度。
答案 3 :(得分:0)
您可以将其更改为:
private static void WriteToDisk<T>(string fileName, T[] vector) where T : struct, IComparable,IComparable<T>
如果要将数组类型保留为数值类型。