ToString和字符串连接 - 意外行为

时间:2015-01-04 20:40:54

标签: c# resharper

根据互联网进行操作

String someString = "" + object1 + object2 + object3;
每个对象都会调用

ToString()

但这不会发生! 这段代码:

String a = "a" + foo;
String b = "b" + foo.ToString();

Console.WriteLine(a);
Console.WriteLine(b);

打印:

a
b("key":"foo")

怎么可能?

我在整个项目中对Resharper进行了全面清理,并且在某些地方破坏了代码,因为它在这样的字符串连接中删除了ToString()!失去了好几个小时......

修改 这个问题发生在我正在使用的一个小型库中。我不能提供非常简短的单文件代码来重现这一点,但我已经用这个库创建了一个小项目并上传到github:

https://github.com/Vistritium/ToStringCSObjectConcat https://github.com/Vistritium/ToStringCSObjectConcat/blob/master/TestString/Program.cs

图书馆长1178行。

2 个答案:

答案 0 :(得分:4)

如果您提供implicit operator将您的班级转换为字符串,则会发生这种情况,例如:

public class Foo
{
    public string Key { get; set; }

    public string Value { get; set; }

    public static implicit operator string(Foo foo)
    {
        return foo == null ? string.Empty : foo.Value;
    }

    public override string ToString()
    {
        var str = string.Empty;
        if (!string.IsNullOrEmpty(Key))
        {
            if (str.Length > 0)
                str += ";";
            str += ("Key=" + Key);
        }
        if (!string.IsNullOrEmpty(Value))
        {
            if (str.Length > 0)
                str += ";";
            str += ("Value=" + Value);
        }
        return str;
    }
}

在那种情况下:

    string a = "a" + new Foo { Key = "foo", Value = "" };
    string b = "b" + new Foo { Key = "foo", Value = "" }.ToString();

    Debug.WriteLine(a); // Prints "a".
    Debug.WriteLine(b); // Prints "bKey=foo

如果您stringFoooverloaded the + operator,也可能会产生此效果。

<强>更新

来自C#语言规范,7.2.2 Operator overloading

  

所有一元和二元运算符都具有在任何表达式中自动可用的预定义实现。除了预定义的实现之外,还可以通过在类和结构(Section 10.9)中包含运算符声明来引入用户定义的实现。用户定义的运算符实现始终优先于预定义的运算符实现:仅当不存在适用的用户定义的运算符实现时,才会考虑预定义的运算符实现。

这就是为什么自定义逻辑优先于标准逻辑调用。

答案 1 :(得分:1)

我刚刚做了这件事并且工作正常

private void button1_Click(object sender, EventArgs e)
{
    var o = new x ();
    string s = "ff" + o;

    Console.WriteLine(s);

}

public class x {

    public override string ToString()
    {
        return "This is string";
    }
}

打印

  

ff这是字符串

这告诉我你做错了什么。我的意思是,没有那么多你做错了,就像你期望的东西不同于你的对象在ToString中产生的那样