C#泛型中的通配符等价物

Axi*_*xus 18 .net c# arrays generics wildcard

假设我有一个泛型类,如下所示:

public class GeneralPropertyMap<T>
{
}
Run Code Online (Sandbox Code Playgroud)

在其他一些类中,我有一个接收数组的方法GeneralPropertyMap<T>.在Java中,为了获取包含任何类型GeneralPropertyMap的方法的数组,将如下所示:

private void TakeGeneralPropertyMap(GeneralPropertyMap<?>[] maps)
{
}
Run Code Online (Sandbox Code Playgroud)

我们使用通配符,以便稍后我们可以调用每个类型的任意类型的TakeGeneralPropertyMap传递,如下所示:GeneralPropertyMapT

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);
Run Code Online (Sandbox Code Playgroud)

我试图弄清楚C#中的等价物并没有成功.有任何想法吗?

Dan*_*ker 18

C#中的泛型比Java中的泛型更有力.因此,要在C#中执行您想要的操作,您必须让GeneralPropertyMap<T>该类继承自该类(或接口)的非泛型版本.

public class GeneralPropertyMap<T> : GeneralPropertyMap
{
}

public class GeneralPropertyMap
{
    // Only you can implement it:
    internal GeneralPropertyMap() { }
}
Run Code Online (Sandbox Code Playgroud)

现在你可以这样做:

private void TakeGeneralPropertyMap(GeneralPropertyMap[] maps)
{
}
Run Code Online (Sandbox Code Playgroud)

和:

GeneralPropertyMap[] maps = new GeneralPropertyMap[3];
maps[0] = new GeneralPropertyMap<String>();
maps[1] = new GeneralPropertyMap<Integer>();
maps[2] = new GeneralPropertyMap<Double>();
TakeGeneralPropertyMap(maps);
Run Code Online (Sandbox Code Playgroud)

  • 它仍然不够好,因为在界面中你很可能希望有一个方法返回或使用通配符来使用"TakeGeneralPropertyMap"方法,你不能这样做,因为我们不希望接口是通用类型.但是,这个答案至少得到了解决.谢谢 :-) (3认同)

Pao*_*lla 8

虽然正如其他人所指出的那样,在c#中与通配符没有确切的对应关系,但是他们的一些用例可以用协方差/逆变来覆盖.

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);
Run Code Online (Sandbox Code Playgroud)

需要注意的是,您不能对值类型使用协方差,因此GeneralPropertyMap<int>()在编译时添加新列表会失败.

cannot convert from 'GeneralPropertyMap<int>' to 'IGeneralPropertyMap<object>'
Run Code Online (Sandbox Code Playgroud)

如果要约束GeneralPropertyMap可包含的类型,则此方法可能比具有非通用版本的类/接口更方便.在这种情况下:

public interface IMyType {}
public class A : IMyType {}
public class B : IMyType {}
public class C : IMyType {}

public interface IGeneralPropertyMap<out T> where T : IMyType {} 
Run Code Online (Sandbox Code Playgroud)

允许你拥有:

var maps = new List<IGeneralPropertyMap<IMyType>> {
    new GeneralPropertyMap<A>(),
    new GeneralPropertyMap<B>() ,
    new GeneralPropertyMap<C>() 
};
TakeGeneralPropertyMap(maps);
Run Code Online (Sandbox Code Playgroud)


Ree*_*sey 5

在 C# 中没有直接的等价物。

在 C# 中,这通常是通过让泛型类实现非泛型接口或基类来完成的:

interface IPropertyMap
{
   // Shared properties
}

public class GeneralPropertyMap<T> : IPropertyMap
{
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以传递以下数组:

IPropertyMap[] maps = new IPropertyMap[3];
// ...

TakePropertyMap(maps);
Run Code Online (Sandbox Code Playgroud)