我实现了一个名为 NonEmptyString 的类,它在非空时不允许创建。我让这个类实现了
IEquatable<NonEmptyString>
和IEquatable<string>
。我实现了IEquatable<string>
。我有 Equals(object obj)
、Equals(NonEmptyString other)
、Equals(string other)
和 GetHashCode()
的覆盖。然后我写了一些测试,发现几乎一切正常。除了 1 种情况,当调用静态 Equals 方法且字符串参数为第一个参数时。请参阅此处此行。
string text = "ASDF123";
NonEmptyString nonEmptyString = NonEmptyString.CreateUnsafe("ASDF123");
Assert.True(text == nonEmptyString);
Assert.True(nonEmptyString == text);
Assert.True(text.Equals(nonEmptyString));
Assert.True(nonEmptyString.Equals(text));
Assert.True(Equals(text, nonEmptyString)); //This is the only one that doesn't work.
Assert.True(Equals(nonEmptyString, text));
我想知道为什么会出现这种情况 - 当我查看对象上 Equals 方法的实现时,它确实调用了虚拟
Equals(object obj)
方法。因此,如果该方法返回 false,那么我预计同样的情况也应该发生在 text.Equals(nonEmptyString)
上 - 但这个方法有效。
我什至尝试重写
==
运算符以这种方式将字符串与 NonEmptyString 进行比较(我真的没想到这会有所帮助,但值得一试)
public static bool operator ==(string obj1, NonEmptyString obj2)
public static bool operator !=(string obj1, NonEmptyString obj2)
public static bool operator ==(NonEmptyString obj1, string obj2)
public static bool operator !=(NonEmptyString obj1, string obj2)
我可以做些什么来完成这项工作吗? 预计这不起作用吗? 这是 .NET 中的错误吗?
这是核心实现(我从中删除了不重要的部分。)
public sealed class NonEmptyString : IEquatable<string>, IEquatable<NonEmptyString>
{
private NonEmptyString(string value)
{
Value = value;
}
public string Value { get; }
public static NonEmptyString CreateUnsafe(string value)
{
if (string.IsNullOrWhiteSpace(value))
{
throw new ArgumentException("You cannot create NonEmptyString from whitespace, empty string or null.");
}
return new NonEmptyString(value);
}
public override int GetHashCode()
{
return Value.GetHashCode();
}
public override bool Equals(object obj)
{
return ReferenceEquals(this, obj) ||
obj is NonEmptyString otherNonEmpty && Equals(otherNonEmpty) ||
obj is string otherString && Equals(otherString);
}
public bool Equals(string other)
{
return Value.Equals(other);
}
public bool Equals(NonEmptyString other)
{
return Value.Equals(other?.Value);
}
public override string ToString()
{
return Value;
}
}
我认为这是因为
Equals(object1, object2)
与调用 object1.ReferenceEquals(object2)
相同,并且 ReferenceEquals()
无法被覆盖。