以下是控制台应用程序的代码段 -
class MyClass
{
public int GetDay(string data22)
{
int returnValue = 0;
if (string.Compare(data22,"THURSDAY") == 0) // true
{
returnValue = (int)DayOfWeek.Thursday;
}
if (data22 == "THURSDAY") //false
{
returnValue = (int)DayOfWeek.Thursday;
}
if (string.Equals(data22, "THURSDAY"))//false
{
returnValue = (int)DayOfWeek.Thursday;
}
return returnValue;
}
}
class Program
{
static void Main(string[] args)
{
string ExecutionDay = "THURSDAY";
MyClass obj1 = new MyClass();
int MyDays = obj1.GetDay(ExecutionDay);
}
}
问题是 - 为什么第一次比较(string.compare)有效,而另外两种比较方法在这个特殊情况下不起作用?
答案 0 :(得分:13)
为什么第一个比较(string.compare)和另外两个比较 比较方法在本特定情况下不起作用
您的代码中有不可见的字符(特别是Left-to-Right mark(感谢@Matthewatson))。您可以使用任何十六进制编辑器查看它们:
string.Compare
覆盖了这一点,而string.Equals
则没有。您可以在the docs中看到它:
来电者注意事项:
字符集包括可忽略的字符。该 比较(String,String)方法时不考虑这样的字符 它执行文化敏感的比较。例如,如果 以下代码在.NET Framework 4或更高版本上运行,a “动物”与“动物”的文化敏感比较(使用柔软的 连字符或U + 00AD)表示两个字符串是等效的。
答案 1 :(得分:3)
ExecutionDay
字符串包含不可见的字符,否则所有检查都将为真
以下行返回不同的长度,分别为9和8
Console.WriteLine(ExecutionDay.Length);
Console.WriteLine("THURSDAY".Length);
答案 2 :(得分:1)
有一个"隐形"
开头的字符string ExecutionDay = "THURSDAY";
它是LEFT-TO-RIGHT MARK。您可以查看:
int len = ExecutionDay.Length; // 9 instead of 8
和
char ch = ExecutionDay[0]; // 8206
答案 3 :(得分:0)
简而言之,CompareTo依赖于文化。例如ß (s sharp from German):
Console.WriteLine("ß Compare ss 1: " + ("ß".CompareTo("ss") == 0));
Console.WriteLine("ß Compare ss 2: " + (String.Compare("ß", "ss", StringComparison.Ordinal) == 0));
Console.WriteLine("ß equals ss: " + "ß".Equals("ss"));
Console.WriteLine("ß == ss: " + ("ß" == "ss"));
会打印出来
ß Compare ss 1: True
ß Compare ss 2: False
ß equals ss: False
ß == ss: False
在您的情况下,您的字符串看起来相同,但不同。通常我觉得看到差异很有帮助,可以通过以下方式完成:
Console.WriteLine(
string.Join(", ",
ExecutionDay
.ToCharArray()
.Select(o =((int)o).ToString(CultureInfo.InvariantCulture))
.AsEnumerable()
)
);
产生字符数代码列表:
8206, 84, 72, 85, 82, 83, 68, 65, 89
unicode中的字符8206
为left-to-right mark
。
这将仅比较值,如果它是值类型或基元。除此之外,它应该用作REFERENCE比较。在C#中,类型字符串是特殊的,并且以下2个断言中的两个都将产生 true :
string ss = getinput();//"SS"
assertTrue("SS"=="SS");
assertTrue( ss =="SS");
在Java中,首先会返回true beacuse JIT运行时优化器,它从代码中收集所有唯一字符串并创建一个使用的表。第二个为false,因为字符串只是不可变字符数组,如果用户输入新内存空间,则参考比较返回 false 。
C# Guidelines for Implementing Equals and the Equality Operator (==)
与 == 不同,Equals方法只是在System.Object中定义的虚拟方法,并且被选择这样做的任何类重写。因此,将使用被覆盖的版本,如果是字符串类型,这意味着将完成内容比较。
覆盖Equals(对象)时请遵循以下准则:
- 实现IComparable的类型必须覆盖Equals(Object)。
- 重写Equals(Object)的类型也必须覆盖GetHashCode;否则,哈希表可能无法正常工作。
- 您应该考虑实现IEquatable接口以支持强类型测试以获得相等性。你的IEquatable.Equals 实现应该返回与Equals一致的结果。
- 如果您的编程语言支持运算符重载,并且您为给定类型重载了相等运算符,则还必须 重写Equals(Object)方法以返回与结果相同的结果 平等运算符。这有助于确保使用的类库代码 Equals(例如ArrayList和Hashtable)的行为方式是 与applicat使用等于运算符的方式一致
C# Implementing the Equals Method
注意
CompareTo 方法主要是为 用于排序或字母顺序操作。它不应该在使用时使用 方法调用的主要目的是确定是否两个 字符串是等价的。确定两个字符串是否为 相当于,调用Equals方法。
此方法使用当前文化执行单词(区分大小写和文化敏感)比较。有关word,string和ordinal排序的更多信息,请参阅System.Globalization.CompareOptions。
来源:Manual