Union
및에 대한 질문이 있습니다 Concat
. 두 경우 모두 동일하게 행동한다고 생각합니다 List<T>
.
var a1 = (new[] { 1, 2 }).Union(new[] { 1, 2 }); // O/P : 1 2
var a2 = (new[] { 1, 2 }).Concat(new[] { 1, 2 }); // O/P : 1 2 1 2
var a3 = (new[] { "1", "2" }).Union(new[] { "1", "2" }); // O/P : "1" "2"
var a4 = (new[] { "1", "2" }).Concat(new[] { "1", "2" }); // O/P : "1" "2" "1" "2"
위의 결과가 예상됩니다.
하지만 List<T>
같은 결과를 얻고 있다면 .
class X
{
public int ID { get; set; }
}
class X1 : X
{
public int ID1 { get; set; }
}
class X2 : X
{
public int ID2 { get; set; }
}
var lstX1 = new List<X1> { new X1 { ID = 10, ID1 = 10 }, new X1 { ID = 10, ID1 = 10 } };
var lstX2 = new List<X2> { new X2 { ID = 10, ID2 = 10 }, new X2 { ID = 10, ID2 = 10 } };
var a5 = lstX1.Cast<X>().Union(lstX2.Cast<X>()); // O/P : a5.Count() = 4
var a6 = lstX1.Cast<X>().Concat(lstX2.Cast<X>()); // O/P : a6.Count() = 4
그러나 두 가지 모두 List<T>
.
어떤 제안을 부탁드립니다.
답변
Union은 Distinct
값을 반환 합니다. 기본적으로 항목의 참조를 비교합니다. 항목에 다른 참조가 있으므로 모두 다른 것으로 간주됩니다. 기본 유형으로 캐스트하면 X
참조가 변경되지 않습니다.
Equals
및 GetHashCode
(고유 항목을 선택하는 데 사용됨)을 재정의하면 항목이 참조로 비교되지 않습니다.
class X
{
public int ID { get; set; }
public override bool Equals(object obj)
{
X x = obj as X;
if (x == null)
return false;
return x.ID == ID;
}
public override int GetHashCode()
{
return ID.GetHashCode();
}
}
그러나 모든 항목의 값은 ID
. 따라서 모든 항목은 여전히 다른 것으로 간주됩니다. 이 같은 여러 항목을 제공 할 것입니다 경우 ID
당신은 차이 볼 Union
과 Concat
:
var lstX1 = new List<X1> { new X1 { ID = 1, ID1 = 10 },
new X1 { ID = 10, ID1 = 100 } };
var lstX2 = new List<X2> { new X2 { ID = 1, ID2 = 20 }, // ID changed here
new X2 { ID = 20, ID2 = 200 } };
var a5 = lstX1.Cast<X>().Union(lstX2.Cast<X>()); // 3 distinct items
var a6 = lstX1.Cast<X>().Concat(lstX2.Cast<X>()); // 4
정수는 값 유형이고 값으로 비교되기 때문에 초기 샘플이 작동합니다.
답변
Concat
말 그대로 첫 번째 시퀀스의 항목과 두 번째 시퀀스의 항목을 반환합니다. Concat
두 개의 2- 항목 시퀀스에 사용 하는 경우 항상 4- 항목 시퀀스를 얻습니다.
Union
본질적으로 Concat
뒤에 Distinct
.
처음 두 경우에는 두 개의 항목 시퀀스로 끝납니다. 그 사이에 각 입력 squence 쌍에는 정확히 두 개의 개별 항목이 있기 때문입니다.
세 번째 경우 두 입력 시퀀스의 4 개 항목이 모두 구별 되기 때문에 4 개 항목 시퀀스로 끝납니다 .
답변
Union
와 Concat
같은 동작합니다 때문에 Union
사용자 정의없이 중복을 감지 할 수 없습니다 IEqualityComparer<X>
. 둘 다 동일한 참조인지 확인하는 것입니다.
public class XComparer: IEqualityComparer<X>
{
public bool Equals(X x1, X x2)
{
if (object.ReferenceEquals(x1, x2))
return true;
if (x1 == null || x2 == null)
return false;
return x1.ID.Equals(x2.ID);
}
public int GetHashCode(X x)
{
return x.ID.GetHashCode();
}
}
이제 다음의 오버로드에서 사용할 수 있습니다 Union
.
var comparer = new XComparer();
a5 = lstX1.Cast<X>().Union(lstX2.Cast<X>(), new XComparer());