繁体   English   中英

通用方法中的运算符重载

[英]Operator overloading in Generic Methods

此代码段来自深度中的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

当main方法改为

    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

我无法理解为什么?

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

如何在第二个代码片段中的Generic方法 AreReferencesEqual中接收参数?

\n

连接时字符串类型有什么变化,以使==运算符不调用String类型的重载Equals方法?

对于字符串的情况,您可能不打算使用引用相等性。 要获得通用方法中的平等和不平等,最好的办法是:

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 ,但也处理nulls等。 对于不等式,它处理空值,以及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 ,因为编译器和运行时的设计是高效的处理字符串; 您使用的任何文字都是“interned”,并且每次在AppDomain中都使用相同的实例。 如果可能的话, 编译器 (而不是运行时)也会执行连接 - 即

    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个字符串; “Jon”(实习),“我的名字是”(实习),以及“我的名字是Jon”的两个不同实例 因此==返回true,引用相等返回false。 但是值相等( EqualityComparer<T>.Default )仍然会返回true。

今天学到了新东西。

我想Jon在其中一个问题中说过,我试着回答。

使用连接构建字符串时,==将为2个匹配值字符串返回true,但它们不指向相同的引用(我认为,它应该由于字符串内部。Jon指出字符串实习适用于常量或文字)。

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

因此,连接版本返回false,而常量(文字字符串)版本返回true。

编辑:我认为乔恩必须以更好的方式解释这个:)
懒惰我,我已经买了这本书,但尚未开始使用它。 :(

它与泛型方法无关,而是与字符串的实例化无关

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

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

这会创建4个字符串。 其中两个是编译时常量,即“Jon”和“My name is”但是在初始化intro1和intro2时,编译器不能说该名称始终为jon并且解析值运行时为每个intro1和intro2创建一个新字符串。

在第二个版本

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

你只有一个字符串,这是一个编译时间常量:“我的名字是Jon”,你将该字符串分配给intro1和intro2,这就是为什么

AreReferencesEqual(intro1, intro2)

在第一种情况下返回false,在第二种情况下返回true

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM