문제
실버 라이트 애플리케이션에 2 개의 문자열을 비교하는 조건이 있습니다. ==
돌아옵니다 거짓 동안 .Equals()
보고 진실.
코드는 다음과 같습니다.
if (((ListBoxItem)lstBaseMenu.SelectedItem).Content.Equals("Energy Attack"))
{
// Execute code
}
if (((ListBoxItem)lstBaseMenu.SelectedItem).Content == "Energy Attack")
{
// Execute code
}
왜 이런 일이 일어나고 있는지에 대한 이유가 있습니까?
해결책
언제 ==
유형의 표현에 사용됩니다 object
, 그것은 해결할 것입니다 System.Object.ReferenceEquals
.
Equals
그냥 a virtual
방법과 동작이 있으므로 재정의 버전이 사용됩니다 ( string
유형은 내용을 비교합니다).
다른 팁
객체 참조를 문자열과 비교할 때 (객체 참조가 문자열을 지칭하는 경우에도) ==
문자열 클래스에 특정한 연산자는 무시됩니다.
일반적으로 (현을 다루지 않을 때, 즉), Equals
비교 가치, 동안 ==
비교 객체 참조. 비교하는 두 개의 객체가 객체의 동일한 정확한 인스턴스를 참조하는 경우, 둘 다 True를 반환하지만 하나는 동일한 내용을 가지고 있고 다른 소스에서 나온 경우 (동일한 데이터를 가진 별도의 인스턴스). 진실을 반환하십시오. 그러나 주석에 언급 된 바와 같이 문자열은 특별한 경우입니다. ==
연산자는 정당하게 문자열 참조 (객체 참조가 아님)를 처리 할 때 별도의 인스턴스 인 경우에도 값 만 비교됩니다. 다음 코드는 행동의 미묘한 차이를 보여줍니다.
string s1 = "test";
string s2 = "test";
string s3 = "test1".Substring(0, 4);
object s4 = s3;
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s2), s1 == s2, s1.Equals(s2));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s3), s1 == s3, s1.Equals(s3));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s4), s1 == s4, s1.Equals(s4));
출력은 다음과 같습니다.
True True True
False True True
False False True
==
그리고 .Equals
둘 다 실제 유형에 정의 된 동작과 통화 사이트의 실제 유형에 따라 다릅니다. 둘 다 단지 모든 유형에서 무시할 수있는 방법 / 연산자 일 뿐이며 저자가 원하는 행동이 주어집니다. 내 경험상 사람들이 구현하는 것이 일반적이라고 생각합니다. .Equals
객체에서는 연산자를 구현하는 것을 소홀히합니다 ==
. 이것은 그것을 의미합니다 .Equals
실제로 값의 평등을 측정합니다 ==
그들이 동일한 참조인지 여부를 측정합니다.
정의가 플럭스 또는 일반 알고리즘을 작성하는 새로운 유형으로 작업 할 때 가장 모범 사례가 다음과 같습니다.
- C#의 참조를 비교하려면 사용합니다.
Object.ReferenceEquals
직접 (일반적인 경우에는 필요하지 않음) - 내가 사용하는 값을 비교하려면
EqualityComparer<T>.Default
어떤 경우에는 내가 사용한다고 느낄 때 ==
모호합니다. 명시 적으로 사용할 것입니다 Object.Reference
모호성을 제거하기 위해 코드와 동일합니다.
Eric Lippert는 최근 CLR에 2 가지 평등 방법이있는 이유에 대한 블로그 게시물을 수행했습니다. 읽을 가치가 있습니다
첫째, 거기 ~이다 차이. 숫자
> 2 == 2.0
True
> 2.Equals(2.0)
False
그리고 끈을 위해
> string x = null;
> x == null
True
> x.Equals(null)
NullReferenceException
두 경우 모두 ==
보다 유용하게 행동합니다 .Equals
객체를 문자열에 던지면 올바르게 작동한다고 덧붙입니다. 이것이 바로 컴파일러가 당신에게 경고를주는 이유입니다.
의도하지 않은 참조 비교; 값 비교를 얻으려면 왼쪽을 'String'유형으로 캐스팅하십시오.
== 운영자1. 피연산자 인 경우 가치 유형 그리고 그들의 가치는 같고, 다른 거짓을 반환합니다. 2. 피연산자 인 경우 참조 유형 문자열을 제외하고 둘 다 동일한 객체를 참조하면 true one false를 반환합니다. 3. 피연산자가 문자열 유형이고 그 값이 같으면 다른 값을 반환합니다.
.equals1. 피연산자가 기준 유형 인 경우 수행됩니다 참조 평등 즉, 둘 다 동일한 객체를 참조하면 true false를 반환합니다. 2. 피연산자가 값 유형 인 경우 == 운영자와 달리 유형을 먼저 확인하고 유형이 동일하면 수행 == 운영자는 거짓을 반환합니다.
내가 이해하는 한 답은 간단합니다.
- == 객체 참조를 비교합니다.
- .equals는 객체 내용을 비교합니다.
- 문자열 데이터 유형은 항상 컨텐츠 비교처럼 작동합니다.
나는 내가 옳기를 바랍니다. 그것은 당신의 질문에 대답했습니다.
정적 버전의 .Equal
방법은 지금까지 언급되지 않았으며, 여기에 이것을 추가하여 3 가지 변형을 요약하고 비교하고 싶습니다.
MyString.Equals("Somestring")) //Method 1
MyString == "Somestring" //Method 2
String.Equals("Somestring", MyString); //Method 3 (static String.Equals method) - better
어디 MyString
코드의 다른 곳에서 나오는 변수입니다.
배경 정보 및 여름 화 :
Java 사용을 사용합니다 ==
문자열을 비교하려면 사용해서는 안됩니다. 두 언어를 모두 사용해야하고 또한 ==
C#에서 더 나은 것으로 대체 할 수도 있습니다.
C#에서는 두 가지 유형 문자열 인 한 방법 1 또는 방법 2를 사용하여 문자열을 비교할 수있는 실질적인 차이는 없습니다. 그러나 하나가 NULL, 하나는 다른 유형 (정수와 같은)이거나 다른 참조를 갖는 객체를 나타내는 경우, 초기 질문에서 볼 수 있듯이 평등의 내용을 비교하는 것이 무엇을 반환하지 않을 수 있음을 경험할 수 있습니다. 당신은 기대합니다.
제안 된 솔루션 :
사용하기 때문에 ==
사용과 정확히 동일하지 않습니다 .Equals
물건을 비교할 때는 사용할 수 있습니다 정적 문자열 대신 방법. 이런 식으로, 양측이 동일한 유형이 아닌 경우에도 여전히 내용을 비교하고 하나가 널이면 예외를 피할 수 있습니다.
bool areEqual = String.Equals("Somestring", MyString);
글을 쓰는 것이 조금 더 있지만, 제 생각에는 사용이 더 안전합니다.
다음은 Microsoft에서 복사 한 정보입니다.
public static bool Equals (string a, string b);
매개 변수
a
끈
비교할 첫 번째 문자열, 또는 null
.
b
끈
비교할 두 번째 문자열, 또는 null
.
보고 Boolean
true
값의 경우 a
값과 동일합니다 b
; 그렇지 않으면, false
. 둘 다 a
그리고 b
~이다 null
, 메소드가 반환됩니다 true
.
나는 여기서 약간 혼란스러워합니다. 런타임 유형의 컨텐츠 유형이 String 유형 인 경우 모두 == 및 Equals는 True를 반환해야합니다. 그러나 이것이 사실이 아닌 것처럼 보이므로 런타임 유형의 컨텐츠 유형이 문자열이 아니며 동등한 호출은 참조 평등을 수행하고 있으며, 이는 동등한 이유 ( "에너지 공격")가 실패하는 이유를 설명합니다. 그러나 두 번째 경우, 과부하가있는 == 정적 연산자를 호출 해야하는 결정은 컴파일 시간에 이루어 지며이 결정은 == (문자열, 문자열) 인 것으로 보입니다. 이것은 내용이 문자열로 암시 적 변환을 제공한다는 것을 나에게 제안합니다.
@bluemonkmn의 이전 답변에는 또 다른 차원이 있습니다. 추가 차원은 @drahcir의 제목 질문에 대한 답이 언급 된 바와 같이 어떻게 우리는 string
값. 설명하려면 :
string s1 = "test";
string s2 = "test";
string s3 = "test1".Substring(0, 4);
object s4 = s3;
string s5 = "te" + "st";
object s6 = s5;
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s2), s1 == s2, s1.Equals(s2));
Console.WriteLine("\n Case1 - A method changes the value:");
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s3), s1 == s3, s1.Equals(s3));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s4), s1 == s4, s1.Equals(s4));
Console.WriteLine("\n Case2 - Having only literals allows to arrive at a literal:");
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s5), s1 == s5, s1.Equals(s5));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s6), s1 == s6, s1.Equals(s6));
출력은 다음과 같습니다.
True True True
Case1 - A method changes the value:
False True True
False False True
Case2 - Having only literals allows to arrive at a literal:
True True True
True True True
답을 하나 더 추가합니다.
.EqualsTo()
방법은 문화와 사례 민감성과 비교할 수있는 규정을 제공합니다.
그만큼 ==
C#의 토큰은 두 가지 평등 확인 연산자에게 사용됩니다. 컴파일러가 해당 토큰을 만나면 비교되는 유형 중 하나가 비교되는 특정 조합 유형 (*)에 대한 평등 작동기 과부하 또는 두 유형을 변환 할 수있는 유형의 조합에 대해 구현했는지 확인합니다. 컴파일러가 그러한 과부하를 찾으면 사용합니다. 그렇지 않으면 두 유형이 참조 유형이고 관련된 클래스가 아닌 경우 (인터페이스 일 수도 있고 관련 클래스 일 수 있음) 컴파일러는 고려됩니다. ==
참조 비교 연산자로서. 조건이 없으면 편집이 실패합니다.
다른 언어는 두 평등 확인 연산자에게 별도의 토큰을 사용합니다. 예를 들어 vb.net에서 =
토큰은 과부하 가능한 평등 확인 연산자에게만 표현식 내에서 사용됩니다. Is
참조 테스트 또는 널 테스트 연산자로 사용됩니다. 사용해야합니다 =
평등 확인 연산자를 무시하지 않는 유형에서 사용하려고 시도하는 것처럼 실패합니다. Is
참조 평등 또는 무효화를 테스트하는 것 이외의 목적으로.
(*) 유형은 일반적으로 자체와 비교하기 위해 평등 만 과부하 만이지만 다른 특정 유형과 비교하기 위해 평등 연산자에 과부하하는 것이 유용 할 수 있습니다. 예를 들어, int
(그리고 IMHO는 평등 연산자를 정의 할 수 있었을 수도 있습니다. float
, 16777217은 16777216f와 동일하게보고하지 않습니다. 그대로, 그러한 연산자가 정의되지 않기 때문에 C#은 int
에게 float
, 평등-점검 연산자가보기 전에 16777216F로 반올림; 그 연산자는 두 개의 동일한 부동 소수점 번호를보고, 반올림을 알지 못한다고보고합니다.
정말 훌륭한 답변과 예!
둘 사이의 근본적인 차이를 추가하고 싶습니다.
다음과 같은 연산자
==
다형성이 아닙니다Equals
~이다
그 개념을 염두에두고, 당신이 예제를 알아 내면 (왼손과 오른손 참조 유형을보고, 유형에 실제로 == 운영자가 과부하되어 있고 재정의되는지 확인/아는 경우) 올바른 답을 얻을 수 있습니다. .
객체를 만들 때 객체에 두 부분이 있습니다. 하나는 내용이고 다른 하나는 해당 내용을 참조합니다.==
내용과 참조를 모두 비교합니다.equals()
내용 만 비교합니다
http://www.codeproject.com/articles/584128/what-is-difference-between-equal equals-and-eq
==
== 연산자는 모든 종류의 두 변수를 비교하는 데 사용될 수 있으며 그것은 단순히 비트를 비교합니다.
int a = 3;
byte b = 3;
if (a == b) { // true }
참고 : INT의 왼쪽에는 더 많은 제로가 있지만 여기서는 신경 쓰지 않습니다.
int a (00000011) == 바이트 B (00000011)
기억 == 운영자는 변수의 비트 패턴에 대해서만 관심이 있습니다.
사용 == 두 참조 (프리미티브)가 힙의 동일한 물체를 나타냅니다.
변수가 기준이든 원시인지 여부에 관계없이 규칙이 동일합니다.
Foo a = new Foo();
Foo b = new Foo();
Foo c = a;
if (a == b) { // false }
if (a == c) { // true }
if (b == c) { // false }
a == C는 true a == b는 false입니다.
비트 패턴은 A와 C의 경우 동일하므로 ==를 사용하여 동일합니다.
동일한():
equals () 메소드를 사용하여 볼 수 있습니다 두 개의 다른 객체가 동일하다면.
"Jane"의 문자를 나타내는 두 개의 다른 문자열 객체와 같은
동일과 ==의 유일한 차이점은 객체 유형 비교입니다. 기준 유형 및 값 유형과 같은 다른 경우에는 거의 동일합니다 (둘 다 비록 평등하거나 참조 평등입니다).
개체 : 동등한 평등 == : 참조 평등
문자열 : (Equals 및 ==는 문자열에 대해 동일하지만 문자열 중 하나가 객체로 변경되면 비교 결과가 다릅니다)와 동일 : 비트 별 평등 == : 비트 별 평등
보다 여기 자세한 설명.