CS1501:方法'ToString'没有重载需要0个参数?

时间:2012-08-21 21:00:31

标签: c# f#

ToString的重载怎么可能不带零参数?零参数ToString是System.Object!

的一部分

编辑以响应近距离投票: 由于我无法将构建服务器升级到.NET 4.5,是否有任何方法可以使此代码与.NET 4.0 / VS 2010编译器?没有为我的重载提供一个完全不同的名称,这并不酷。

  • 有问题的对象是一个F#Discriminated Union,它覆盖从System.Object继承的ToString方法。
  • 被覆盖的ToString由C#项目中的代码调用,该项目属于同一解决方案。
  • 这一切都运行良好,直到我为我的歧视联盟添加了额外的ToString重载,这需要一个参数。
  • 它在我的本地计算机上完全构建和运行(VS 2012,所有针对.NET 4.0的项目)
  • 它在构建服务器(.NET 4.0)上失败 - 一旦我将ToString的1参数重载添加到我的区分联合中,标题中的C#编译器错误就会出现。

我想最简单的解决方法是将我的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"

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

2 个答案:

答案 0 :(得分:6)

这只是部分答案,但我注意到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

,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

区别在于方法签名中的hidebysig注释。如果添加了hidebysig,则该方法将隐藏共享相同名称和签名的其他实现(在基类中),而如果省略hidebysig,则将隐藏具有相同名称的所有其他实现即使签名不同。 This stack overflow question包含一个描述hidebysig的好答案。

所以虽然这个答案没有解决你的问题,但它解释了为什么它不能在VS2010中编译。

答案 1 :(得分:5)

我不得不承认,这是我第一次使用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"

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

如果这不是你想要的,我会道歉...但这是我能想到的,如果有人认为这是错误的方式,请说出原因!