2009-02-09 3 views
20

제네릭 클래스의 메서드를 호출해야하는 곳에서 응용 프로그램을 개발하고 있으며 인스턴스의 실제 형식에 대해서는 신경 쓰지 않습니다. 다음 Java 코드 비슷해 : 나는 서둘러에 있던 때C# generics의 Java 와일드 카드에 해당하는 것은 무엇입니까

public class Item<T>{ 
    private T item; 

    public doSomething(){...} 
} 

... 
public void processItems(Item<?>[] items){ 
for(Item<?> item : items) 
    item.doSomething(); 
} 

은, 그래서 내가 호출하는 데 필요한 방법과 인터페이스를 정의하여 내 문제를 해결하고 일반 클래스를 구현했다.

public interface IItem 
{ 
    void doSomething(); 
} 

public class Item<T> : IItem { 
    private T item; 

    public void doSomething(){...} 
} 

... 
public void processItems(IItem[] items) 
{ 
foreach(IItem item in items) 
    item.doSomething(); 
} 

이 해결 방법은 제대로 작동하지만 동일한 동작을 얻으려면 올바른 방법을 알고 싶습니다.

편집 :

내가 processItems의 호출자가 실제 유형을 모르는 것을 참조하는 것을 잊었다. 사실 생각은 배열이 processItems에 인수로 전달되면 혼합 된 유형을 포함 할 수 있다는 것입니다. 닷넷에 이러한 배열을 가질 수 없기 때문에 비 제너릭 기본 클래스 나 인터페이스를 사용하는 것이 유일한 방법 인 것 같습니다.

답변

25

방법은 일반적인 있도록하는 것이 작업을 수행하는 일반적인 방법 :

public void ProcessItems<T>(Item<T>[] items) { 
    foreach(Item<T> item in items) 
    item.DoSomething(); 
} 

가이 유형을 알고 발신자를 가정하면, 타입 추론은 명시 적으로 지정할 필요가 없습니다 것을 의미한다. 예를 들면 다음과 같습니다.

Item<int> items = new Item<int>(); // And then populate... 
processor.ProcessItems(items); 

그렇다면 유형에 관계없는 작업을 지정하는 비 제네릭 인터페이스를 만드는 것이 유용 할 수 있습니다. 정확한 사용 사례에 크게 좌우 될 것입니다.

+0

블러 흐, 너무 빨리 몇 초. : P –

+0

그래, 나를 때려. 하지만 발신자의 예를 사용하여 편집 할 수 있습니까? –

+0

그냥'ProcessItems (data); ' –

1

.NET 일반 구현에서 유형 매개 변수를 생략 할 수있는 방법은 없습니다. 이것은 의도적으로 설계된 것입니다. 실제로 이것은 유형 지우기 기반 구현 때문에 Java에서만 가능합니다.

기본이 아닌 일반 인터페이스 만 사용할 수 있습니다 (IEnumerable<T>IEnumerable).

0

Jon의 게시물에 더 가깝습니다. 메서드 generic (템플릿)을 만들면 이러한 종류의 기능에 대한 요구 사항이 무효화됩니다 (<? > 사용). 유형을 일반 클래스/함수로 항상 제공 할 수 있으며 필요한 유형을 모르는 경우 불쾌한 메소드/클래스를 포괄적으로 만들 수 있습니다 ... 궁극적으로 사용자는 호출 할 때 유형을 제공해야합니다 이러한 함수 또는 일반 클래스를 사용하여 코드를 컴파일 할 수 있습니다. 그렇지 않으면 컴파일러 오류가 발생합니다.

3

매개 변수가없는 일부 메소드를 호출하려는 경우 ... 이미 계약이 있습니다 : Action.

public void processItems(IEnumerable<Action> actions) 
{ 
    foreach(Action t in actions) 
    t(); 
} 

가 클라이언트 : 그것은 내가

if (o instanceof Collection<?>) doSoemthing((Collection<?>)o); 

같은 구조를 했어 자바에서 포팅 물건에 왔을 때이 같은 문제로 어려움을 겪고 있었어요

List<Animal> zoo = GetZoo(); 
List<Action> thingsToDo = new List<Action>(); 
// 
thingsToDo.AddRange(zoo 
    .OfType<Elephant>() 
    .Select<Elephant, Action>(e => e.Trumpet)); 
thingsToDo.AddRange(zoo 
    .OfType<Lion>() 
    .Select<Lion, Action>(l => l.Roar)); 
thingsToDo.AddRange(zoo 
    .OfType<Monkey>() 
    .Select<Monkey, Action>(m => m.ThrowPoo)); 
// 
processItems(thingsToDo); 
0

다행히이 변합니다 일반 ICollection도 비 generic ICollection이기 때문에 순수한 객체로 처리해야하는 경우 여전히 가능합니다.

if (o is ICollection) DoSomething((ICollection)o); 

그런 식으로 우리가 수집하는 요소의 실제 유형에 대해 신경 쓰지 않기 때문에 여기에있는 모든 것이 객체입니다. 여기에 유의하십시오. 컬렉션에 기본 유형 (예 : int 또는 byte)이있는 경우 autoboxing이 실행되면 성능이 저하 될 수 있습니다.

관련 문제