Let's say I have a generic class as follows:
public class GeneralPropertyMap<T> { }
In some other class I have a method that takes in an array of GeneralPropertyMap<T>
. In Java, in order to take in an array that contains any type of GeneralPropertyMap
the method would look like this:
private void TakeGeneralPropertyMap(GeneralPropertyMap<?>[] maps) { }
We use the wildcard so that later we can call TakeGeneralPropertyMap
passing a bunch of GeneralPropertyMap
with any type for T
each, like this:
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);
I'm trying to figure out an equivalent in C# with no success. Any ideas?
Alternatively referred to as a wild character or wildcard character, a wildcard is a symbol used to replace or represent one or more characters. The most common wildcards are the asterisk (*), which represents one or more characters and question mark (?) that represents a single character.
A wildcard can replace one or more characters in a string of text or numbers. The most common wildcard is the asterisk (*). It's important to note that wildcard searches are case sensitive.
An asterisk (*) may be used to specify any number of characters. It is typically used at the end of a root word, when it is referred to as "truncation." This is great when you want to search for variable endings of a root word.
Generics in C# make stronger guarantees than generics in Java. Therefore, to do what you want in C#, you have to let the GeneralPropertyMap<T>
class inherit from a non-generic version of that class (or interface).
public class GeneralPropertyMap<T> : GeneralPropertyMap { } public class GeneralPropertyMap { // Only you can implement it: internal GeneralPropertyMap() { } }
Now you can do:
private void TakeGeneralPropertyMap(GeneralPropertyMap[] maps) { }
And:
GeneralPropertyMap[] maps = new GeneralPropertyMap[3]; maps[0] = new GeneralPropertyMap<String>(); maps[1] = new GeneralPropertyMap<Integer>(); maps[2] = new GeneralPropertyMap<Double>(); TakeGeneralPropertyMap(maps);
While, as others have noted, there's no exact correspondence to wildcards in c#, some of their use cases can be covered with 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);
The caveat is that you can't use covariance with value types, so adding a new GeneralPropertyMap<int>()
to our list fails at compile time.
cannot convert from 'GeneralPropertyMap<int>' to 'IGeneralPropertyMap<object>'
This approach may be more convenient than having a non-generic version of your classes/interfaces in case you want to constrain the types that GeneralPropertyMap
can contain. In that case:
public interface IMyType {} public class A : IMyType {} public class B : IMyType {} public class C : IMyType {} public interface IGeneralPropertyMap<out T> where T : IMyType {}
allows you to have:
var maps = new List<IGeneralPropertyMap<IMyType>> { new GeneralPropertyMap<A>(), new GeneralPropertyMap<B>() , new GeneralPropertyMap<C>() }; TakeGeneralPropertyMap(maps);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With