在C#generics中,Java通配符的等价物是什么

我正在开发一个应用程序,我需要调用generics类的方法,而不关心实例的实际类型。 像下面的Java代码:

public class Item{ private T item; public doSomething(){...} } ... public void processItems(Item[] items){ for(Item item : items) item.doSomething(); } 

当时我很着急,所以我通过使用我需要调用的方法定义一个接口并使generics类实现它来解决我的问题。

 public interface IItem { void doSomething(); } public class Item : IItem { private T item; public void doSomething(){...} } ... public void processItems(IItem[] items) { foreach(IItem item in items) item.doSomething(); } 

这种解决方法工作正常,但我想知道实现相同行为的正确方法是什么。

编辑:

我忘了引用processItems的调用者不知道实际的类型。 实际上,这个想法是作为参数传递给processItems的数组可能包含混合类型。 由于在.Net中不可能有这样的数组,因此使用非generics基类或接口似乎是唯一的方法。

执行此操作的常规方法是使方法通用:

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

假设调用者知道类型,类型推断应该意味着他们不必明确指定它。 例如:

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

话虽如此,创建一个指定类型不可知操作的非generics接口也很有用。 这在很大程度上取决于您的确切用例。

我看到你只想调用一些没有参数的方法……已经有了一个合同: Action

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

客户:

 List zoo = GetZoo(); List thingsToDo = new List(); // thingsToDo.AddRange(zoo .OfType() .Select(e => e.Trumpet)); thingsToDo.AddRange(zoo .OfType() .Select(l => l.Roar)); thingsToDo.AddRange(zoo .OfType() .Select(m => m.ThrowPoo)); // processItems(thingsToDo); 

在.NETgenerics实现中,你无法省略类型参数; 这是设计的。 事实上,由于其基于类型擦除的实现,这只能在Java中实现。

您只能使用基本的非generics接口(想想IEnumerableIEnumerable )。

继Jon的post。 使方法通用(模板)否定了对这种function的要求(使用<?>)。 您总是可以将类型提供给通用类/函数,如果您不知道需要什么类型,也可以使违规方法/类通用…最终用户在调用时必须提供类型这样的函数或使用generics类,代码能够编译…否则你会得到一些编译器错误。

当我从Java那里移植东西时,我一直在努力解决同样的问题

 if (o instanceof Collection) doSoemthing((Collection)o); 

幸运的是,事实上ICollection也是一个非通用的ICollection,如果有人需要将其中的元素视为纯对象,它仍然是可能的:

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

这样,因为我们不关心集合中元素的实际类型,所以我们在这里得到的是对象。 这里有一个注释:如果集合中包含原始类型(例如int或byte),那么自动装箱可能会引发性能损失。