2014-12-04 6 views
3

나는 WeakReference의 유형 검사 및 캐스팅을 피할 수 있도록 4.5 일반 구현을 사용하여 WeakReference List를 작성하려고합니다. 그러나 WeakReference<T>은 공분산을 지원하지 않으므로 해결 방법을 설정하려고합니다.List <WeakReference <T>>을 만들 수 있습니까?

나는 각 T가 특정 상속 체인에서 유형이 될 수 있기 때문에 가능해야한다고 생각합니다. (가 아닌 상속 이후) 내가 WeakReference를위한 래퍼 클래스를 만드는 시도했습니다

public class Animal { } 
public class Tiger : Animal { } 
public class Wolf : Animal { } 

var mylist = new List<WeakReference<Animal>>(); 

mylist.Add(new WeakReference<Animal>(new Animal())); 
mylist.Add(new WeakReference<Tiger>(new Tiger())); 
mylist.Add(new WeakReference<Wolf>(new Wolf())); 

,하지만 작동하지 않습니다 : 그래서, 내가 생각하고 무슨 일이 라인을 따라 할 것이다. 무슨 일이 있어도, 목록에는 이외의 형식의 WeakReference을 사용할 수 없습니다.

내 자신의 일반 WeakReference 구현을 만들 수는 있지만, 그 유형을 캐스팅 할 때부터 그 점을 무시하는 것처럼 보일 수 있습니다. 나는 어떤 문서도 찾을 수 없지만, 프레임 워크 버전이이를 더 잘 처리한다고 가정합니다.

내가 처리 할 수있는 다른 방법이 있습니까, 아니면 잘못된 트리를 짖고 있습니까?

+0

WeakReference '은 공변수로 'T'라는 일반 매개 변수를 정의하지 않습니다. 새로운 WeakReference (새로운 Wolf())'를 컬렉션에 추가 할 수 있습니다. –

+0

클래스는 결코 공변 적이 지 않습니다. 인터페이스와 대리인 만 가능합니다. 그리고'WeakReference '은 공변 할 수 없습니다. 왜냐하면'T'가 입력 및 출력 위치에 모두 나타나기 때문입니다. –

답변

5

WeakReference이이 값이 설정 될 수 있기 때문에, 불변이며, 그 않을 것 그것이 공변량이라면 유효해야한다. 이를 공변하게하려면 참조 주위에 읽기 전용 래퍼를 만들고 인터페이스도 사용해야합니다.

public interface IReadOnlyWeakReference<out T> 
{ 
    T Value { get; } 
} 

public class WeakReferenceWrapper<T> : IReadOnlyWeakReference<T> 
    where T : class 
{ 
    private WeakReference<T> reference; 
    public WeakReferenceWrapper(WeakReference<T> reference) 
    { 
     this.reference = reference; 
    } 

    public T Value 
    { 
     get 
     { 
      T output; 
      if (reference.TryGetTarget(out output)) 
       return output; 
      else 
       return default(T); 
     } 
    } 
} 

변환에 대한 확장 방법도 다소 편리 :

public static IReadOnlyWeakReference<T> AsReadOnly<T>(
    this WeakReference<T> reference) 
    where T : class 
{ 
    return new WeakReferenceWrapper<T>(reference); 
} 

지금 우리가 쓸 수 있습니다 :

var mylist = new List<IReadOnlyWeakReference<Animal>>(); 

mylist.Add(new WeakReference<Animal>(new Animal()).AsReadOnly()); 
mylist.Add(new WeakReference<Tiger>(new Tiger()).AsReadOnly()); 
mylist.Add(new WeakReference<Wolf>(new Wolf()).AsReadOnly()); 
+0

다음 질문, 사용 방법은? –

+0

@SriramSakthivel 답변에 맞습니다. – Servy

+1

아니요, 목록을 소비하는 방법은 무엇입니까? OP가'IReadOnlyWeakReference '타입의리스트이기 때문에 여전히'Value'를'Animal' 만 얻고있을 것입니다. –

1

나의 제안이있는 WeakReferences (목록)의 목록을 작성하고이 같은를 IEnumerable로 노출하는 것입니다

private List<WeakReference> innerList = new List<WeakReference>(); 

public IEnumerable<T> List 
{ 
    get 
    { 
     return (this.innerList.Where(x => x.Target is T).Select(x => (T) x.Target)); 
    } 
} 
1

당신은 단순히 WeakReference<Animal> 자체를 사용할 수, 어쨌든 목록 유형 List<WeakReference<Animal>>이다 따라서 공분산을 사용하더라도 더 많은 파생 멤버에 액세스 할 수 없습니다.

var mylist = new List<WeakReference<Animal>>();  
mylist.Add(new WeakReference<Animal>(new Animal())); 
mylist.Add(new WeakReference<Animal>(new Tiger())); 
mylist.Add(new WeakReference<Animal>(new Wolf())); 

또는 더 구체적인 유형을 유지하려는 경우, 방법이 있습니다. 나는 그것을 방문자 패턴으로 먼저 풀어 봤다. See if that helps.