对象数组中相等性的字符串比较:意外错误

时间:2015-04-04 00:15:48

标签: c#

请考虑以下事项:

using System;

namespace ObjectArrayWeirdness
{
    public class Program
    {
        public static object[] Change(object[] set)
        {
            object[] result = new object[set.Length];

            // If the following two lines are replaced with:
            // result[0] = "ab";
            // then ArrayEquals will evaluate true.
            result[0] = "a";
            result[0] += "b";
            return result;
        }

        public static bool ArrayEquals(object[] a, object[] b)
        {
            if (a.Length != b.Length) return false;
            for (int i = 0; i < a.Length; i++)
            {
                if (a[i] != b[i])
                {
                    return false;
                }
            }
            return true;
        }


        static void Main(string[] args)
        {
            object[] expected = { "ab" };
            object[] actual = Change(new object[] { 1 });
            Console.WriteLine(ArrayEquals(expected, actual));
        }
    }
}

Dotnetfiddle for convenience

输出:

false

result[0].GetType()的输出:

System.String

我的问题:

  1. ArrayEquals中的比较是否会因为比较对象引用而不是值而失败?

  2. 如果是这种情况,为什么在一步(不使用+=)分配到result[0]时正确的字符串成功?

  3. 我必须承认我期望正常的字符串比较,因为GetType()a[0]b[0]标识为字符串。

2 个答案:

答案 0 :(得分:4)

  

ArrayEquals中的比较是否因为它比较对象引用而不是值而失败?

  

如果是这种情况,为什么在一步(不使用+ =)分配到结果[0]中正确的字符串时它会成功?

这是编译器优化。在编译时声明两个相同的文字字符串时,编译器会将它们折叠为单个对象实例以节省空间。但是如果字符串是在运行时构造的,那么你最终会得到两个独立的字符串对象。

答案 1 :(得分:1)

究竟会发生什么。您正在比较对象引用。但请注意,字符串会覆盖==!=运算符以比较文字。因此,如果将数组项转换为字符串,则您的比较将按预期工作:

if ((string)a[i] != (string)b[i])
{
    return false;
}