ienumerable에서 ienumerable 로 캐스팅
-
03-07-2019 - |
문제
최근에 나는 C#에서 매우 놀라운 동작을 발견했습니다. 나는 취하는 방법이 있었다 IEnumerable<Object>
매개 변수로서 나는 통과했다IEnumerable<string>
그러나 불가능합니다. C#에서는 이것이 불가능한 이유보다 모든 것이 객체로 향상 될 수 있습니까? 나에게 완전히 혼란 스러워요. 이 문제에 대해 누군가 나를 정리 해주세요.
해결책
이에 대한 기술 용어는 제네릭이 C# 3.0 이상에서 변하지 않는다는 것입니다. C#4.0부터 캐스트가 작동합니다.
불변의 의미는 일반적인 유형이기 때문에 두 가지 일반 유형 사이에 관계가 없다는 것입니다. 매개 변수 관련이 있습니다 (즉, 서로의 하위 또는 초대형).
예에서는 IEnumerable<object>
그리고 IEnumerable<string>
, 문자열은 객체의 하위 유형이기 때문입니다. 그들은 문자열과 int와 같은 완전히 관련이없는 두 가지 유형으로 간주됩니다 (여전히 둘 다 객체의 하위 유형이지만 모든 것이 있습니다).
이 문제에 대한 몇 가지 해결 방법과 예외가 있습니다.
먼저 각 문자열을 개별적으로 객체에 캐스트 할 수 있습니다. .NET 3.0을 사용하는 경우 Cast<T>()
확장 방법. 그렇지 않으면 Foreach를 사용하여 결과를 원하는 정적 유형의 새로운 변수에 넣을 수 있습니다.
둘째, 배열은 참조 유형에 대한 예외이며, 즉 문자열 [] 유형을 통과하는 객체 [] 유형을 설명하는 메소드로 전달됩니다.
다른 팁
다른 사람들이 지적했듯이 제네릭 유형은 변하지 않습니다. IEnumerable<T>
공동 변수 일 수 있지만 C#은 현재 변형 지정을 지원하지 않습니다. C# 4.0은 변형을 지원할 것으로 예상되므로 향후 지원 될 수 있습니다.
지금이 문제를 해결하려면 LINQ 확장 방법을 사용할 수 있습니다. Cast<object>()
. 당신이라는 메소드가 있다고 가정합니다 Foo
그것은 필요합니다 IEnumerable<object>>
. 당신은 이것을 이렇게 부를 수 있습니다.
Foo(stringEnumerable.Cast<object>());
가장 쉬운 방법 IEnumerable<string>
기능을 요구합니다 IEnumerable<object>
다음과 같은 기능을 변환하는 것입니다.
public IEnumerable<object> convert<T>(IEnumerable<T> enumerable)
{
foreach (T o in enumerable)
yield return o;
}
C# 4가 나오면 공분산과 비밀화를 지원하기 때문에 이것은 악의적이지 않습니다.
당신은 사용해야합니다
IEnumerable<T>
다른 유형으로 전달하려면 T를 쿼리하여 어떤 유형인지 확인할 수 있습니다.
이것에 대해 생각하는 좋은 방법은 "이것을 할 수 있다면 어떻게 될까요?"라고 스스로에게 물어 보는 것입니다. 다음 예를 들어보세요 :
IEnumerable<String> strings=...;
IEnumerable<Object> objects = strings; // assume this were legal
objects.Add(new Integer(5)); // what the...
우리는 방금 문자열 목록에 정수를 추가했습니다. 컴파일러는 유형 안전을 보존하기 위해이를 수행합니다.