在泛型方法操作符重载(Operator overloading in Generic Methods

2019-09-17 06:55发布

此代码段是从C#中的深度

    static bool AreReferencesEqual<T>(T first, T second)
        where T : class
    {
        return first == second;
    }

    static void Main()
    {
        string name = "Jon";
        string intro1 = "My name is " + name;
        string intro2 = "My name is " + name;
        Console.WriteLine(intro1 == intro2);
        Console.WriteLine(AreReferencesEqual(intro1, intro2));
    }

上面的代码片段的输出是

True 
False

当主方法变更为

    static void Main()
    {
        string intro1 = "My name is Jon";
        string intro2 = "My name is Jon";
        Console.WriteLine(intro1 == intro2);
        Console.WriteLine(AreReferencesEqual(intro1, intro2));
    }

上面的代码片段的输出是

True 
True

我无法捉摸为什么?

编辑:一旦你了解字符串实习以下问题不适用。

如何在泛型方法接收的参数AreReferencesEqual在第二代码片段?

什么样的变化,以字符串类型,当它被连接起来,使==操作符不叫String类型的重载equals方法?

Answer 1:

对字符串的情况下,你可能不打算使用引用相等。 要访问等式和不等式的泛型方法,最好的办法是:

EqualityComparer<T>.Default.Equals(x,y); // for equality
Comparer<T>.Default.Compare(x,y); // for inequality

static bool AreValuesEqual<T>(T first, T second)
    where T : class
{
    return EqualityComparer<T>.Default.Equals(first,second);
}

这仍然使用重载Equals ,但处理空值等了。 对于不等式,这个处理空值,并且两个IComparable<T>IComparable

对于其他运营商,看到MiscUtil 。


重的问题; 如果是:

    string intro1 = "My name is Jon";
    string intro2 = "My name is Jon";
    Console.WriteLine(intro1 == intro2);
    Console.WriteLine(AreReferencesEqual(intro1, intro2));

你得到truetrue ,因为编译器和运行时的设计是高效的处理字符串; 您使用的任何文字被“拘留”和相同的情况下使用,每次在你的AppDomain。 编译器 (而非运行时)也做了CONCAT如果可能的话-即

    string intro1 = "My name is " + "Jon";
    string intro2 = "My name is " + "Jon";
    Console.WriteLine(intro1 == intro2);
    Console.WriteLine(AreReferencesEqual(intro1, intro2));

完全相同的代码前面的例子。 有没有什么不同。 不过,如果你强迫它在运行时连接字符串,它假定他们很可能是短暂的,所以他们拘留/重新使用。 所以在的情况下:

    string name = "Jon";
    string intro1 = "My name is " + name;
    string intro2 = "My name is " + name;
    Console.WriteLine(intro1 == intro2);
    Console.WriteLine(AreReferencesEqual(intro1, intro2));

你有4串; “乔恩”(实习),“我的名字是”(实习),和“我的名字是乔恩” 两个不同的实例 。 因此==返回true,并且引用相等返回false。 但价值相等( EqualityComparer<T>.Default )仍然会返回true。



Answer 2:

今天学到了新的东西。

我想乔恩说的一个问题,我试图回答。

当你建立一个使用串联的字符串,==将返回true,匹配值的2串,但他们不指向同一个参考(我想,应该是由于字符串实习。乔恩指出该字符串实习恒定或工程文字)。

在通用版本,它在调用object.ReferenceEquals(比==不同,在字符串的情况下,确实==值比较)。

其结果是,级联版本返回false而定(文本字符串)版本返回true。

编辑:我觉得乔恩必须围绕在一个更好的方式来解释这个:)
懒惰的我来说,我已经买了这本书,但还没有得到它开始。 :(



Answer 3:

它无关,与一般的方法,但琴弦的实例

在主要的第一个版本,你有:

string name = "Jon";
string intro1 = "My name is " + name;
string intro2 = "My name is " + name;

这产生4个字符串。 其中两个编译时间常数,即“乔恩”和初始化intro1何时intro2编译器不能说名字总是乔恩和解析值运行时使每个intro1和intro2的一个新的字符串“我的名字是”但是。

在第二个版本

string intro1 = "My name is Jon";
string intro2 = "My name is Jon";

你只有一个字符串,那是一个编译时间常数:“我的名字是乔恩”,你分配一个字符串都intro1和intro2,这就是为什么

AreReferencesEqual(intro1, intro2)

返回在第一种情况下虚假和真实在第二



文章来源: Operator overloading in Generic Methods