假设我有一个通用类,如下所示:
public class GeneralPropertyMap<T>
{
}
在其他一些类中,我有一个接收GeneralPropertyMap<T>
数组的方法。在Java中,为了接收包含任何类型GeneralPropertyMap
的数组,该方法将如下所示:
private void TakeGeneralPropertyMap(GeneralPropertyMap<?>[] maps)
{
}
我们使用通配符,以便稍后我们可以调用TakeGeneralPropertyMap
传递一堆GeneralPropertyMap
,其中包含T
的任何类型,如下所示:
GeneralPropertyMap<?>[] maps = new GeneralPropertyMap<?>[3];
maps[0] = new GeneralPropertyMap<String>();
maps[1] = new GeneralPropertyMap<Integer>();
maps[2] = new GeneralPropertyMap<Double>();
//And finally pass the array in.
TakeGeneralPropertyMap(maps);
我试图找出C#中的等价物并没有成功。有什么想法吗?
答案 0 :(得分:18)
C#中的泛型比Java中的泛型更有力。因此,要在C#中执行您想要的操作,您必须让GeneralPropertyMap<T>
类继承自该类(或接口)的非泛型版本。
public class GeneralPropertyMap<T> : GeneralPropertyMap
{
}
public class GeneralPropertyMap
{
// Only you can implement it:
internal GeneralPropertyMap() { }
}
现在你可以做到:
private void TakeGeneralPropertyMap(GeneralPropertyMap[] maps)
{
}
和
GeneralPropertyMap[] maps = new GeneralPropertyMap[3];
maps[0] = new GeneralPropertyMap<String>();
maps[1] = new GeneralPropertyMap<Integer>();
maps[2] = new GeneralPropertyMap<Double>();
TakeGeneralPropertyMap(maps);
答案 1 :(得分:9)
虽然正如其他人所指出的那样,c#中与通配符没有确切的对应关系,但covariance/contravariance可以涵盖一些用例。
public interface IGeneralPropertyMap<out T> {} // a class can't be covariant, so
// we need to introduce an interface...
public class GeneralPropertyMap<T> : IGeneralPropertyMap<T> {} // .. and have our class
// inherit from it
//now our method becomes something like
private void TakeGeneralPropertyMap<T>(IList<IGeneralPropertyMap<T>> maps){}
// and you can do
var maps = new List<IGeneralPropertyMap<Object>> {
new GeneralPropertyMap<String>(),
new GeneralPropertyMap<Regex>()
};
//And finally pass the array in.
TakeGeneralPropertyMap<Object>(maps);
需要注意的是,您不能对值类型使用协方差,因此在编译时向列表中添加新的GeneralPropertyMap<int>()
会失败。
cannot convert from 'GeneralPropertyMap<int>' to 'IGeneralPropertyMap<object>'
如果要约束GeneralPropertyMap
可以包含的类型,这种方法可能比拥有非通用版本的类/接口更方便。在那种情况下:
public interface IMyType {}
public class A : IMyType {}
public class B : IMyType {}
public class C : IMyType {}
public interface IGeneralPropertyMap<out T> where T : IMyType {}
允许您拥有:
var maps = new List<IGeneralPropertyMap<IMyType>> {
new GeneralPropertyMap<A>(),
new GeneralPropertyMap<B>() ,
new GeneralPropertyMap<C>()
};
TakeGeneralPropertyMap(maps);
答案 2 :(得分:3)
在C#中没有直接的等价物。
在C#中,通常可以通过让泛型类实现非泛型接口或基类来完成:
interface IPropertyMap
{
// Shared properties
}
public class GeneralPropertyMap<T> : IPropertyMap
{
}
然后你可以传递这些数组:
IPropertyMap[] maps = new IPropertyMap[3];
// ...
TakePropertyMap(maps);
答案 3 :(得分:0)
从GeneralPropertyMap
(IGeneralPropertyMap
)的成员创建一个界面,然后以IGeneralPropertyMap[]
作为参数。
答案 4 :(得分:0)
实际上,通过使用dynamic可以非常接近通配符。如果您有一个非泛型超类,这也很好用。
例如:
<param name="columns" type="int" min="3" max="100" _gui-text="Cols">6</param>
<param name="ratio" type="float" min="0.5" max="1" precision="3" appearance="full" _gui-text="ratio">1.0</param>
这是如何工作的,请参见C#文档here。