如何不对ToString重载采取零参数?零参数ToString是System.Object的一部分!
编辑以响应近距离投票: 由于我无法将构建服务器升级到.NET 4.5,有没有办法让这个代码与.NET 4.0/VS 2010编译器一起工作?没有给我的超载一个完全不同的名字,这只是不酷.
我想最简单的解决方法是将我的ToString重载重命名为其他东西,但这很奇怪.
这是一个简单的复制品.您可以在此处下载包含此代码的解决方案的zip文件:http://dl.dropbox.com/u/1742470/CS1501_Repro.zip
在VS 2010中编译该解决方案将失败"CS1501:方法'ToString'没有重载需要0个参数".在VS 2012中编译它将工作得很好.在这两种情况下,我们都以.NET Framework 4为目标.
F#
namespace CS1501_Repro.FSharp
open System
[<Serializable>]
type MyDiscriminatedUnion =
| Foo of int list
| Bar of string
| Baz of int
| Fizz of float
| Buzz of DateTimeOffset
override this.ToString() =
"Zero Arguments"
member this.ToString(lookup:Func<int,string>) =
"One Argument"
Run Code Online (Sandbox Code Playgroud)
C#
using System;
using CS1501_Repro.FSharp;
namespace CS1501_Repro.CSharp
{
public class Caller
{
private MyDiscriminatedUnion _item;
public Caller(MyDiscriminatedUnion item)
{
_item = item;
}
public string DoThing()
{
return _item.ToString();
}
public string DoOtherThing()
{
return _item.ToString(i => i.ToString());
}
}
}
Run Code Online (Sandbox Code Playgroud)
这只是一个部分答案,但我注意到VS2010和VS2012为F#类生成不同的IL.如果您查看IL的ToString(lookup:Func<int,string>)方法,那么您将看到VS2010中的输出是:
.method public instance string ToString(class [mscorlib]System.Func`2<int32,string> lookup) cil managed
{
// Code size 7 (0x7)
.maxstack 3
IL_0000: nop
IL_0001: ldstr "One Argument"
IL_0006: ret
} // end of method MyDiscriminatedUnion::ToString
Run Code Online (Sandbox Code Playgroud)
而VS2012的输出是:
.method public hidebysig instance string
ToString(class [mscorlib]System.Func`2<int32,string> lookup) cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: nop
IL_0001: ldstr "One Argument"
IL_0006: ret
} // end of method MyDiscriminatedUnion::ToString
Run Code Online (Sandbox Code Playgroud)
区别在于hidebysig方法签名中的注释.如果hidebysig添加,则该方法将隐藏共享相同名称和签名的其他实现(在基类中),而如果hidebysig省略,则即使签名不同,它也将隐藏具有相同名称的所有其他实现.这个堆栈溢出问题包含一个很好的答案hidebysig.
所以虽然这个答案并没有解决你的问题,但它解释了为什么它不能在VS2010中编译.
我不得不承认,这是我第一次使用F#,所以这个解决方案可能不是最优雅的,但是,你提到ToString()是System.Object的一部分......
我通过在DoThing()方法中添加一行代码来解决这个问题,该方法将_item分配给object,然后从对象调用ToString(),在这个例子中给出了所需的结果:
F#代码(未更改)
type MyDiscriminatedUnion =
| Foo of int list
| Bar of string
| Baz of int
| Fizz of float
| Buzz of DateTimeOffset
override this.ToString() = "Zero Arguments"
member this.ToString(lookup:Func<int,string>) = "One Argument"
Run Code Online (Sandbox Code Playgroud)
C#代码(请参阅DoThing()方法中的更改)
public class Caller
{
private Module1.MyDiscriminatedUnion _item;
public Caller(Module1.MyDiscriminatedUnion item)
{
_item = item;
}
public string DoThing()
{
object result = _item; //assign to object
return result.ToString(); //call ToString() on object
}
public string DoOtherThing()
{
return _item.ToString(i => i.ToString());
}
}
Run Code Online (Sandbox Code Playgroud)
如果这不是你想要的,我会道歉...但这是我能想到的,如果有人认为这是错误的方式,请说出原因!