IDictionary .NET 4에서 공변이 아님
IDictionary<TKey, TValue>
.NET 4 / 실버 라이트 4는 공분산을 지원하지 않는, 즉 내가 할 수 없어
IDictionary<string, object> myDict = new Dictionary<string, string>();
IEnumerable<T>
지금 s로 할 수있는 것과 유사합니다 .
아마도 KeyValuePair<TKey, TValue>
공변 적이 지 않기 때문일 것입니다. 적어도 값에 대해서는 사전에서 공분산이 허용되어야한다고 생각합니다.
그래서 그것은 버그입니까 아니면 기능입니까? 아마도 .NET 37.4에서 올 것인가?
업데이트 (2 년 후) :
거기에있을 것입니다 IReadOnlyDictionary<TKey, TValue>
.NET 4.5하지만, 공변 될하거나하지 않습니다 :·/
그것은에서 유래하기 때문에 IEnumerable<KeyValuePair<TKey, TValue>>
, 그리고 KeyValuePair<TKey, TValue>
공변 될 수 없습니다, 따라서 인터페이스하지 않고.
BCL 팀은 많은 것을 재 설계하고 ICovariantPair<TKey, TValue>
대신 일부 를 사용해야 합니다. 또한 강력한 형식의 인덱서 this[TKey key]
는 공변 인터페이스에 사용할 수 없습니다. 비슷한 목적은 GetValue<>(this IReadOnlyDictionary<TKey, TValue> self, TKey key)
내부적으로 실제 구현을 호출해야하는 확장 메서드를 어딘가에 배치하는 방식으로 만 달성 할 수 있습니다 . 이는 매우 지저분한 접근 방식으로 보입니다.
기능입니다. .NET 4.0은 안전한 공분산 만 지원 합니다 . 언급 한 캐스트는 가능한 경우 사전에 문자열이 아닌 요소를 추가 할 수 있으므로 잠재적으로 위험합니다.
IDictionary<string, object> myDict = new Dictionary<string, string>();
myDict["hello"] = 5; // not an string
반면에는 IEnumerable<T>
읽기 전용 인터페이스입니다. T
유형의 매개 변수는 출력 위치 (의 반환 형식에 Current
속성)가 치료하는 안전 그래서 IEnumerable<string>
int로서 IEnumerable<object>
.
하지만 당신은 말할 수 있습니다
myDict.Add("Hello, world!", new DateTime(2010, 1, 27));
비참하게 실패 할 것입니다. 문제는 입력이 입력 및 출력 위치 모두에서 사용 된다는 것 TValue
입니다 IDictionary<TKey, TValue>
. 재치 :
myDict.Add(key, value);
과
TValue value = myDict[key];
그래서 그것은 버그입니까 아니면 기능입니까?
의도적으로 설계된 것입니다.
아마도 .NET 37.4에서 올 것인가?
아니요, 본질적으로 안전하지 않습니다.
비슷한 문제가 있었지만 더 전문화 된 파생 유형이 있습니다 (모든 것이 파생되는 객체보다는)
트릭은 메서드를 일반화하고 관련 제한을 두는 where 절을 넣는 것입니다. 기본 유형 및 파생 유형을 다루고 있다고 가정하면 다음이 작동합니다.
using System;
using System.Collections.Generic;
namespace GenericsTest
{
class Program
{
static void Main(string[] args)
{
Program p = new Program();
p.Run();
}
private void Run()
{
Dictionary<long, SpecialType1> a = new Dictionary<long, SpecialType1> {
{ 1, new SpecialType1 { BaseData = "hello", Special1 = 1 } },
{ 2, new SpecialType1 { BaseData = "goodbye", Special1 = 2 } } };
Test(a);
}
void Test<Y>(Dictionary<long, Y> data) where Y : BaseType
{
foreach (BaseType x in data.Values)
{
Console.Out.WriteLine(x.BaseData);
}
}
}
public class BaseType
{
public string BaseData { get; set; }
}
public class SpecialType1 : BaseType
{
public int Special1 { get; set; }
}
}
.NET 4 만 지원 밖으로 공분산을하지 에 . IEnumerable은 읽기 전용이므로 IEnumerable과 함께 작동합니다.
특정 유형의 유용한 공분산에 대한 해결 방법 IDictionary
public static class DictionaryExtensions
{
public static IReadOnlyDictionary<TKey, IEnumerable<TValue>> ToReadOnlyDictionary<TKey, TValue>(
this IDictionary<TKey, List<TValue>> toWrap)
{
var intermediate = toWrap.ToDictionary(a => a.Key, a => a.Value!=null ?
a.Value.ToArray().AsEnumerable() : null);
var wrapper = new ReadOnlyDictionary<TKey, IEnumerable<TValue>>(intermediate);
return wrapper;
}
}
참고URL : https://stackoverflow.com/questions/2149589/idictionarytkey-tvalue-in-net-4-not-covariant
'Programing' 카테고리의 다른 글
서비스를 클래스에 주입하는 방법 (구성 요소가 아님) (0) | 2020.12.13 |
---|---|
npm 패키지 목록에서 무엇을 중복 제거합니까? (0) | 2020.12.13 |
@import 대 링크 (0) | 2020.12.13 |
정의되지 않은 동작을 감지하는 C ++ 구현? (0) | 2020.12.13 |
논문 작성에 Git 사용 (0) | 2020.12.13 |