2010-04-10 4 views
3

행동의이 종류는 C# 4.0는 C# .NET 4.0 및 제네릭

에 가능하면 사람이 내가 강력하게 형식화 된 유지하고 싶은 객체 계층 구조를 가지고 나에게 말할 수 있는지 궁금 해서요. 이

class ItemBase {} 

class ItemType<T> where T : ItemBase 
{ 
    T Base { get; set; } 
} 


class EquipmentBase : ItemBase {} 
class EquipmentType : ItemType<EquipmentBase> {} 

같은 뭔가 내가 할 수 있기를 원하는 것은이

ItemType item = new EquipmentType(); 

같은 뭔가를하고 난 item.Base 유형의 ItemBase을 반환합니다. 기본적으로 강력한 타이핑없이 기본 클래스에 제네릭을 강력하게 입력하는 것이 현명한지 알고 싶습니다. 이 덕분에 ItemType을 EquipmentType으로 다시 캐스팅 할 수 있고 모든 강력한 형식화를 다시 얻을 수 있습니다.

답변

4

당신은 당신이 할 수있는 것 공분산에 대해 얘기하고

  1. 일반 공분산 만에 작동 기본 클래스가 아닌 인터페이스, 배열 및 대리자 형식
  2. ItemType 클래스는 T를 입력/출력 형식 매개 변수로 사용하여 T를 받고 T를 반환한다는 것을 의미합니다.

허용되는 경우 다음 코드는 컴파일 할 수 있어야하지만 런타임에는 실패하므로 2 번이 주된 문제입니다.

// this will not work 
ItemType<object> item = new EquipmentType(); 
item.Base = new Object(); // this seems ok but clearly isn't allowed 

Covariance and Contravariance FAQ

0

없음

나는 모든 잘못이 생각 할 수있다 ... ItemType가 멀리 컴파일러에 관한 한 ItemType<EquipmentBase> 또는 ItemType<Foo>에서 별도의 유형이기 때문이다. 세 가지 모두 고유 한 유형으로 취급되며 서로를 대표 할 수 없습니다.

클래스 선언에서 ItemType<T>으로 선언 했으므로 ItemType은 컴파일되지 않는 정의되지 않은 유형입니다.

는 기껏해야, 당신은 EquipmentType 또는 ItemType<EquipmentBase>하지만 ItemType<PersonType>에서 파생 된 다른 클래스를 대표하는 ItemType<EquipmentBase> 개체를 사용할 수 있습니다.

ItemType<object> item = new EquipmentType(); 

당신은 다음과 같은 이유로 인해 C# 4에서이 작업을 수행 할 수 있습니다 :

+1

내 대답에 언급 된 2 가지 이유 때문에 C# 4에서도 작동하지 않습니다. 그러나 ItemType 이 대신 IItemType 인 경우에도 T 및 in 매개 변수로 필요한 사실은 원하는 사용법을 효과적으로 배제합니다. – Josh

0

나는 C# 4.0의 새로운 기능 거기에 당신을 도울 것입니다 생각하지 않습니다. 그러나 제네릭이 소개 된 이래로 이미 작동하는 방법이 있습니다. 제네릭 클래스와 동일한 이름을 가진 추상 기본 클래스를 만들고 원하는 모든 멤버를 넣고 인수를 수락하거나 반환 할 필요가없는 방법을 사용할 수 있습니다.

class ItemBase { 
} 

abstract class ItemType { 
    public ItemBase Base { 
     get { return GetItemBase(); } 
     set { SetItemBase(value); } 
    } 

    protected abstract void SetItemBase(ItemBase value); 

    protected abstract ItemBase GetItemBase(); 
} 

class ItemType<T> : ItemType where T : ItemBase { 
    protected override sealed void SetItemBase(ItemBase value) { 
     Base = (T) value; 
    } 

    protected override sealed ItemBase GetItemBase() { 
     return Base; 
    } 

    public new T Base { get; set; } 
}