Java 및 .NET 제네릭에 익숙하며 Java 프로젝트에서 많이 사용하는 Class<X>
구조를 사용합니다. 내가 가장 좋아하는 용도 중 하나는 Hibernate와 같은 외부 코드에서 반환되는 Java의 비 제네릭 컬렉션을 처리하는 것입니다. (나는 Hibernate의 최신 버전이 제네릭을 지원할 것이라고 생각하지만, 확실하지는 않습니다. 그 이후의 이전 버전은 우리가 이제까지을 변경 한 경우 업데이트해야 할 것이다 너무 많은 코드가 장기 실행 프로젝트) 기능은 다음과 같이 작동합니다.
public <X> List<X> TypedList(List<?> lst, Class<X> cls) {
return (List<X>) lst;
}
그것은 모두 매우 간단하고 중요한 일이 함수에 전달할 더미 객체를 만들 필요가 없으며 단지 다음과 같이 호출해야합니다.
List<MyObject> myLst = TypedList(lst, MyObject.class);
주목해야 할 또 다른 중요한 사항은 다음과 같습니다. cls 매개 변수가 전혀 사용되지 않습니다. X에 대한 구체적인 유형을 제공하는 방법 일뿐입니다.
C#에서 이와 동일한 작업을 수행하는 방식이 조금 다릅니다. 당신은 동일한 기능은 다음과 같이 보일 것이라고 생각 :
public List<X> TypedList<X>(IList lst)
{
return (List<X>) lst;
}
하지만 당신은 죽은 잘못입니다.
문제는 자바가 기본적으로 코드가 실제로 컴파일 할 때, 모든 일반 매개 변수는 코드에서 제거되는 것을 의미 유형 소거라는 트릭을 사용한다는 것입니다. 따라서 Java 가상 머신의 세계에는 List<X>
또는 다른 제네릭과 같은 것이 없으며 모두 단순한 List
및 기타 일반 유형이 아닙니다. 즉, 제네릭은 코드 작성을 돕기위한 용도로만 사용되며 런타임에는 시행되지 않습니다.
그러나 C#에서는 런타임에 적용되는 형식 삭제가없고 은입니다. 이것은 상기 함수와 함께 사용하면 다음과 같은 런타임 예외를 생성 할 것이라는 점을 의미
List<object> lstObj = TypedList<object>(new List<string>());
이유 List<string>
List<object>
과는 완전히 다른 두 종류로 간주된다는 것이다. 컴파일러 오류가 발생하지 않고 List<object> lstObj = (List<object>) new List<string>();
도 수행 할 수 없습니다. 이것은 함수가 전달 된 동일한 객체를 반환 할 수 없음을 의미합니다. 우리는 이어야합니다. 올바른 유형의 새 개체를 만들고 그 개체를 반환해야합니다.가장 기본적인 형태는 다음과 같습니다.
public List<X> TypedList<X>(IList lst)
{
List<X> lstOut = new List<X>();
for (int i = 0; i < lst.Count; i++)
{
if (lst[i] is X) lstOut.Add((X) lst[i]);
}
return lstOut;
}
오히려 지루하고 보일러 코드이지만 작동합니다. 훨씬 더 짧고 깨끗한 것을 위해 LINQ가 오늘을 구하기 위해 왔습니다. 다음 체크 아웃 :
public List<X> TypedList<X>(IList lst)
{
return lst.OfType<X>().ToList();
}
OfType<X>()
는 타입 X (또는 후손)의이다 LST에있는 모든 항목을 잡고 수없는 그 어떤 건너 뜁니다. ToList()
은 OfType<X>()
에서 전달 된 모든 구성원을 포함하는 List<X>
을 새로 만듭니다. 이 방법의 또 다른 장점은 lst 매개 변수를 실제로 IList
에서 IEnumberable
으로 변경할 수 있으며 모든 컬렉션 유형에 의해 구현된다는 것입니다.
또 다른 한가지는 유형에 대한 변환을하지 않으며 형식 검사 만 수행한다는 것입니다. 따라서 List<long>
을 사용하여 List<int>
또는 List<string>
으로 변환하려면 다른 작업을 수행해야합니다. LINQ와 함께,이 여전히 매우 간단 할 것 :
이
List<long> lstLng = new List<long>();
lstLng.Add(1);
List<int> lstInt = lstLng.Cast<int>().ToList();
List<string> lstStr = lstLng.Select(lng => lng.ToString()).ToList();
[참고 :. 당신이 lng => lng.ToString()
부분에 익숙하지 않은 경우가 람다 식라고]
Cast<int>()
달리 OfType<int>()
, 실제로 각 항목을 int로 변환하고 변환하지 못하는 항목은 건너 뜁니다. Select()
을 사용하면 원하는 거의 모든 종류의 코드를 사용하여 기존 컬렉션에서 완전히 새로운 컬렉션을 만들 수 있습니다.
실제 예제를 사용하면 일반 유형의 함수를 사용할 때 .NET과 Java의 차이점을 더 잘 이해할 수 있기를 바랍니다.
http://msdn.microsoft.com/en-us/library/ms379564(v=vs.80).aspx – asawyer
저는 C# 프로그래머가 아니지만이 관용구는 훨씬 덜 일반적이라고 생각합니다. C#에서는 형식 지우기가 없기 때문에 C#에서. 일반 유형 정보는 런타임에 손실되지 않고 유지됩니다. –
하나는 없다고 생각합니다. – clamchoda