Long story short, I would like to be able to store generics using different type parameters in an array, by using a parent type to all the types used. MSDN mentioned it was impossible, as generics were invariant types, but a comment stated that this changed since the 4.0 framework.
Here is a basic example of what I would like to do:
public class Animal
{
}
public class Dog : Animal
{
}
public class Cat : Animal
{
}
public class MyGeneric<T>
{ }
public class MyInheritedGeneric<T> : MyGeneric<T>
{ }
static void Main(string[] args)
{
MyGeneric<Animal>[] myGenericArray = new MyGeneric<Animal>[]
{
new MyGeneric<Dog>(),
new MyInheritedGeneric<Cat>()
};
}
This returns the similar errors:
Cannot implicitly convert type
'InheritanceTest.Program.MyGeneric<InheritanceTest.Program.Dog>' to
'InheritanceTest.Program.MyGeneric<InheritanceTest.Program.Animal>'
Cannot implicitly convert type
'InheritanceTest.Program.MyInheritedGeneric<InheritanceTest.Program.Cat>'
to 'InheritanceTest.Program.MyGeneric<InheritanceTest.Program.Animal>'
Is there any way to store generics in an array using the parent class of the type, or is this simply impossible? I really hope it is possible, otherwise it will make my program a nightmare...
EDIT: A bit more context!
I am making classes to generate enemies in a game. I call them Templates (nothing to do with actual template classes, I could very well have called them Blueprints or Factories). An enemy constructor takes in a Template, which it uses to determine its own values. When the game loads, the templates are used to generate all enemies, using their Generate() function, which returns an array of the corresponding type they are assigned to produce. All the objects to be created with a template are to have a constructor taking a template as their sole parameter.
public class Template<T>
{
protected static Random random = new Random();
protected int _amount;
public int Amount
{
get { return _amount; }
}
public virtual T CreateInstance()
{
return (T)Activator.CreateInstance(typeof(T), this);
}
public virtual T[] Generate()
{
T[] objects = new T[Amount];
for (int i = 0; i < Amount; ++i)
objects[i] = CreateInstance();
return objects;
}
}
Here is a summary of the BasicZombie.cs file, which contains the actual enemy class and the template.
class Tpl_BasicZombie : Tpl_Enemy<BasicZombie>
{
public Tpl_BasicZombie()
{
_hp = 4;
_speed = 3;
_amount = 10;
}
}
class BasicZombie : GroundEnemy
{
public BasicZombie(Tpl_BasicZombie template)
: base(template, TextureManager.Get("zombie_base"), 1, 8)
{ }
public void StuffHappens()
{ }
}
When loading the game, I would like to go through all the templates in an array to load enemies from them. I know that I could do this manually, but every time I will create a new type of enemy I would need to add it manually to the code (thus probably forgetting more than once).
My two options were:
1- Use a generic, and the above problem ensues.
2- Use a non-generic, and store the type inside, which would anchor the return type Generate() function. This would mean the generate function would output an array of objects, array which would need to be converted to the suitable type every single time a template generates an array of enemies.
I have a space in my head that tells me there is an elegant solution to all this, and I hope it is right!
Yes, C# 4 supports generic variants - but only in the declarations of interfaces and delegates, so you won't be able to do it in this case. Of course you could potentially create an interface:
public interface IGeneric<out T>
and then implement that in your classes, at which point you could create an IGeneric<Animal>.
If you can give more details about what you're trying to achieve, we may be able to help you find an alternative approach.
Jon Skeet's info aside, you might be able to do something like this:
public MyGeneric<T2> ToOtherType<T2>()
{
if (typeof(T2).IsAssignableFrom(typeof(T)))
{
// todo: get the object
return null;
}
else
throw new ArgumentException();
}
new MyGeneric<Dog>().ToOtherType<Animal>(),
new MyInheritedGeneric<Cat>().ToOtherType<Animal>()
If an array is going to hold more than one type of item, the items are going to have to be stored in heap objects which are separate from the array itself (if some of the types are structs, they'll have to either be boxed or stored as a field in a generic type which derives from a non-generic one). In most cases, the simplest thing to do will be to identify a common ancestor type for everything you'll be storing in the array, and simply typecast array elements as needed. There are a few cases where that won't be feasible, however. If, for example, your collection is going to hold objects whose type is unknown but is constrained to more than one interface, it will be necessary to pass those objects to generic routines whose method type parameter is similarly constrained, and the types that may be passed to your routine have no common ancestor which satisfies all constraints, there won't be any single type to which all members of your collection can be cast that would allow them to be passed as a suitable generic.
If the objects in your collection will only be passed to a small number of routines, it may be possible to have the generic method which adds items construct delegates to suitably invoke all the necessary routines and store those delegates as part of the collection. Lambda expressions or anonymous delegates may be convenient for this.
For example, suppose one will need to be able to feed items that are stored in a list to the Wibble<T> method of various IWibbler objects and the Wobble<T> method of various IWobbler objects, where the T types have interface constraints I1 and I2.
interface IWibbler { void Wibble<T>(T param, int param) where T : I1,I2; }
interface IWobbler { void Wobble<T>(T param, string param) where T: I1,I2; }
private struct WibbleWobbleDelegateSet
{
public Action<IWibbler, int> Wibble;
public Action<IWobbler, string> Wobble;
static WibbleWobbleDelegateSet Create<T>(T param) where T: I1, I2
{
var ret = new WibbleWobbleDelegateSet ();
ret.Wibble = (IWibbler wibbler, int p2) => { wibbler.Wibble<T>(param, p2); };
ret.Wobble = (IWobbler wobbler, string p2) => { wobbler.Wobble<T>(param, p2); };
return ret;
}
}
Calling WibbleWobbleDelegateSet.Create<T>(T param), with a suitably-constrained param, will yield a non-generic structure which contains delegates that can be used to pass the parameter supplied at struct creation to any IWibbler.Wibble<T>() or IWobbler.Wobble<T>() method.
This approach is only directly usable if the list of routines that will be called is known. If one needs to be able to call arbitrary routines with constrained generic parameters, it's possible to do that either with some tricky interfaces or with Reflection, but such things get more complicated.
Related
Suppose I have a basic inheritance structure:
public class Letter {...}
public class A : Letter {...}
public class B : Letter {...}
public class C : Letter {...}
public class Number {...}
public class One : Number {...}
I want to define an array of Types such that only Types which inherit from Letter are valid. So a sample array might look like:
(type)[] myArray = new (type)[] {typeof(A), typeof(B), typeof(C)};
But the assignment
myArray[0] = typeof(One);
would fail. Is it possible to define such a structure?
All types are instances of System.Type, being the same statically. Therefore, doing this using a conventional array is not possible. One option is to create a data structure that only allows addition through type parameters:
internal sealed class LetterTypeSet : IReadOnlyCollection<Type>
{
readonly ISet<Type> types = new HashSet<Type>();
public IEnumerator<Type> GetEnumerator() => this.types.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
public int Count => this.types.Count;
public bool Add<T>()
where T : Letter
{
return this.types.Add(typeof (T));
}
}
This would allow:
var letters = new LetterTypeSet();
letters.Add<A>(); //ok
letters.Add<B>(); //ok
letters.Add<One>(); //CS0311 "The type 'One' cannot be used ..."
Note: I'm using a ISet<T> as the underlying data structure, you may or may not want to use a List<T> instead depending on the requirements.
I don't think it is possible that you can use the type system to enforce this: typeof returns an instance of System.Type. This is a generic class and there is no aspect of the typesystem that can enforce that only subtypes of a certain type can be stored. So using the typesystem for this is probably not the way to go.
There are some alternatives however:
You could use contract contracts and hope that your can verify this at compile time. For instance:
Type[] myArray = new (type)[] {typeof(A), typeof(B), typeof(C)};
//...
Contract.Ensures(Contract. ForAll (myArray,t => typeof(Letter).IsAassignableFrom(t));
Note however that it is an undecidable problem, and that the contract verifier can only give a conservative answer.
You could define a data-structure (probably a subset of an ICollection<Type> that enforces this at the front door. For instance:
public class SubTypeList<T> : IList<Type> {
private readonly List<Type> innerList = new List<Type>();
public void Add (Type type) {
if(typeof(T).IsAssignableFrom(type)) {
innerList.Add(type);
} else {
throw new ArgumentException("The given System.Type must be an inherit from T!");
}
}
//Implement other methods
//...
}
You can always define an array of Letter, and only Letter objects and types derived from it can be assigned to the elements. However, when you get an element of the array, the compiler will think it is a Letter. That may be what you want. If not, you can discover what it really is at run-time:
if (myArray[i] is A)
{
A objA = myArray[i] as A;
...
The is and as operators are used in these downcasts to verify that the downcast is valid.
Or, better, you can define behavioral properties and methods of your Letter base class that allow the caller to obtain the behaviors of the derived classes without having to know what the exact class of the object is.
myArray[i].DrawSelf(Point ptStart)
and make the various derived classes responsible for knowing how to draw themselves starting at a given location.
Please check the following codes segments:
public interface ICountable { }
public class Counter<T>
where T : ICountable
{
public int Count(IEnumerable<T> items)
{
return 0;
}
public int Count(T Item)
{
return 0;
}
}
public class Counter
{
public int Count<T>(IEnumerable<T> items)
where T : ICountable
{
return 0;
}
public int Count<T>(T Item)
where T : ICountable
{
return 0;
}
}
The two versions of Counter differ only in the specification of the generic parameter. One of them defines as a generic type parameter, the other as a generic argument. Both restrict the method arguments to implement the ICountable interface. I will call them specific and non specific respectively.
Now, I am defining a class that implements the ICountable interface, and a collection of instances:
public class CItem : ICountable { }
var countables = new List<CItem>();
Then, I would like to use both Counter classes on the collection.
var specific = new Counter<CItem>();
var nonspecific = new Counter();
specific.Count(countables);
nonspecific.Count(countables);
The specific counter recognizes that the countables collection should fall into the signature int Count(IEnumerable), but the non specific version does not. I get the error:
The type 'System.Collections.Generic.List<CItem>' cannot be used as
type parameter 'T' in the generic type or method
'Counter.Count<T>(T)'. There is no implicit reference conversion from
List<CItem>' to ICountable.
It seems that the non specific version uses the wrong signature for the collection.
Why do they behave differently?
How can the non specific version be specified in order to behave the same as the other?
Note: I know this example is not realistic. However, I faced this problem in a quite complicate scenario with extension methods. I use these classes for the sake of simplicity
Thanks in advance
The problem with nonspecific class is that compiler doesn't know the type T in compile time that's why it cannot select correct overload for method Count<T>(). However if you set generic type constraints compiler now knows what type to expect...
If you'll comment out your method with signature public int Count<T>(T Item) it'll compile because it'll use method with correct signature (which is public int Count<T>(IEnumerable<T> items))
It'll also compile and run if you help compiler to infer type by casting your List to IEnumerable<CItem> explicitly :
nonspecific.Count(countables as IEnumerable<CItem>);
Have a look at simplified scenario :
static string A<T>(IEnumerable<T> collection)
{
return "method for ienumerable";
}
static string A<T>(T item)
{
return "method for single element";
}
static void Main(string[] args)
{
List<int> numbers = new List<int>() { 5, 3, 7 };
Console.WriteLine(A(numbers));
}
Output : "method for single element"
If I remember correctly (will try to find a reference in the specification), the T method is chosen because it's an exact match for the type.
The type inference, correctly identifies that both generic methods are applicable, as Count<CItem>(IEnumerable<CItem> items) and Count<List<CItem>>(List<CItem> items). However, the first one loses in the overload resolution, as the second one is more specific. The constraints only come in play after that, so you get a compile time error.
If you declare your countables using
IEnumerable<CItem> countables = new List<CItem>();
then the choice becomes Count<CItem>(IEnumerable<CItem> items) and Count<IEnumerable<CItem>>(IEnumerable<CItem> items) and the first one wins the overload resolution.
In my opinion, the reason why the compiler thinks that you are calling Counter.Count(T) instead of Counter.Count< T >(IEnumerable< T >) is because the later one requires a conversion from List to IEnumerable. And that has a priority less than using the former signature Counter.Count(T), which result in an error.
I think it's better that you change the method name of the one taking an IEnumerble as the argument into something like CountAll. The some thing .NET framework does for List.Remove and List.RemoveAll. It's a good practice to make your code more specific rather than letting the compiler to do all the decisions.
Java 7 now has this "diamond syntax" where I can do things like ArrayList<int> = new ArrayList<>();
I'm wondering if C# has a similar syntax that I can take advantage of.
For example, I have this part of a class:
class MyClass
{
public List<double[][]> Prototypes; // each prototype is a array of array of doubles
public MyClass()
{
Prototypes = new List<double[][]>; // I'd rather do List<>, in case I change the representation of a prototype later
}
}
Does anyone know if this is possible, and if so, how I might go about using it?
No, there's nothing quite like the diamond syntax in C#. The closest you could come would be to have something like this:
public static class Lists
{
public static List<T> NewList<T>(List<T> ignored)
{
return new List<T>();
}
}
Then:
public MyClass()
{
ProtoTypes = Lists.NewList(ProtoTypes);
}
That just uses normal generic type inference for methods to get T. Note that the value of the parameter is completely ignored - it's only the compile-time type which is important.
Personally I think this is pretty ugly, and I'd just use the constructor directly. If you change the type of ProtoTypes the compiler will spot the difference, and it won't take long at all to fix it up...
EDIT: Two alternatives to consider:
A similar method, but with an out parameter:
public static class Lists
{
public static void NewList<T>(out List<T> list)
{
list = new List<T>();
}
}
...
Lists.NewList(out ProtoTypes);
The same method, but as an extension method, with the name New:
public static class Lists
{
public static List<T> New<T>(this List<T> list)
{
return new List<T>();
}
}
...
ProtoTypes = ProtoTypes.New();
I prefer the first approach to either of these :)
As Jon Skeet said and Eric Lippert backed up, constructors for generic classes in C# cannot infer their types from their parameters or the type of the variable to which the construction is assigned. The go-to pattern when this type of behavior is useful is usually a static generic factory method, which can infer its own generic type from those of its parameters. Tuple.Create() is an example; give it any list of parameters up to 8, and it will create a strongly-typed generic Tuple with those parameters as the data fields. This doesn't work out well for your case, however.
When the variable will be local, consider doing it the other way around; use variable type inference, via the var keyword:
var Prototypes = new List<double[][]>();
This is how the C# team decided to cut down on typing when instantiating variables. Locals are created - and change - much more often than instance variables, and this approach makes C# code look a little more like JavaScript.
As Jon showed, it's possible to hide the mess, but you'll create more of a mess in the process. Here's another possibility using .NET 3.5/4.0's Expression features:
public static string GetName(this Expression<Func<object>> expr)
{
if (expr.Body.NodeType == ExpressionType.MemberAccess)
return ((MemberExpression) expr.Body).Member.Name;
//most value type lambdas will need this because creating the Expression
//from the lambda adds a conversion step.
if (expr.Body.NodeType == ExpressionType.Convert
&& ((UnaryExpression)expr.Body).Operand.NodeType
== ExpressionType.MemberAccess)
return ((MemberExpression)((UnaryExpression)expr.Body).Operand)
.Member.Name;
throw new ArgumentException(
"Argument 'expr' must be of the form ()=>variableName.");
}
public static void InitializeNew(this object me, params Expression<Func<T>>[] exprs)
where T:new()
{
var myType = me.GetType();
foreach(var expr in exprs)
{
var memberName = expr.GetName()
var myMember = myType.GetMember(memberName,
BindingFlags.Instance|BindingFlags.Public
|BindingFlags.NonPublic|BindingFlags.FlattenHierarchy,
MemberTypes.Field|MemberTypes.Property);
if(myMember == null)
throw new InvalidOperationException(
"Only property or field members are valid as expression parameters");
//it'd be nice to put these under some umbrella of "DataMembers",
//abstracting the GetValue/SetValue methods
if(myMember.MemberType == MemberTypes.Field)
((FieldInfo)myMember).SetValue(me, new T());
else
((PropertyInfo)myMember).SetValue(me, new T());
}
}
//usage
class MyClass
{
public List<double[][]> list1;
public List<double[][]> list2;
public MyOtherObject object1;
public MyClass()
{
this.Initialize(()=>list1, ()=>list2);
this.Initialize(()=>object1); //each call can only have parameters of one type
}
}
The implication is obvious here; it's more trouble than it's worth.
To explain why I seemingly just had this laying around; the above is an adaptation of a method I use to throw ArgumentNullExceptions based on passed parameters, which requires the values to be encapsulated within Expressions in order to retain the names of the actual parameters from the calling method. In that situation, the complexity behind the scenes is reduced since all I need in the main helper is a check for null, and the added complexity saves me a lot more than I spend, by allowing me to one-line my null checks in every method and constructor of the codebase.
I recommend ReSharper as a long-term solution to reducing this typing. When the type of an assignment target is known (as it is for instance fields and properties), and you type = new, ReSharper will pop up a suggestion for the type of the constructor, and auto-fill it for you if you want. If you change either the type or constructor afterward, R# will flag the assignment as inconsistent, and you can tell R# to change whichever one you want to match the other.
If you just want to reduce code verbosity there is an opposite shortand syntax: the var operator
Old: List<int> intList = new List<int>();
New: var intList = new List<int>();
At least you write List only once
I'm a bit confused about why/when I'd ever want to use a generic method since a non-generic method can access the generic members of its containing class and be passed generic arguments anyway.
So, using a canned example that likely misses the point (yet highlights why I'm asking this question), why would I do this:
public class SomeGeneric<T>
{
public T Swap<T>(ref T a, ref T b)
{
T tmp = a;
a = b;
b = tmp;
}
}
over
public class SomeGeneric<T>
{
public T Swap(ref T a, ref T b)
{
T tmp = a;
a = b;
b = tmp;
}
}
this?
Or, really, why would I want to use a generic method at all?
You'd typically use a generic method in a type that isn't generic.
For example, look at the Enumerable class. It defines the generic extension methods for most of the LINQ fucntionaltiy, but itself isn't generic.
You also might want a generic method within a generic type, but only if the generic method used a different generic type specifier.
This lets you write something like the following:
class Foo<T> where T : IConvertible, IComparable<T>
{
int CompareTo<U>(U other) where U : IConvertible
{
// Convert to this
T otherConverted = Convert.ChangeType(other, typeof(T));
return this.CompareTo(otherConverted);
}
}
(Granted, this is a bit contrived, but does compile and work correctly for Foo<int> comparing to a double, etc)
What if the containing class is not generic? What if it has different generic type parameters?
The first example does not make much sense, because class parameter is not used. Consider another example though:
public class SomeGeneric<T>
{
public K ConvertTo<T>(T a)
{
return CodeThatConvertsTtoK(a);
}
}
and its usage:
new SomeGeneric<int>().ConvertToInt("ten");
A common scenario for method level type parameters are extension methods because they must be declared in a non-generic static class. But they are required for every generic member in a non-generic type.
public static class Extensions
{
public static void Foo<A, B>(this A a, B b) { [...] }
public static T Bar<T>(this String input) { [...] }
public static U FooBar<V, W>(this V v, W w) { [...] }
}
If both the class and the method are generic, the type parameters ("generic parameters") must have different names, of course. There can't be two different things named T like in your first example.
If your method is non-static (as it seems), if you choose to make the containing class generic, the type will have to be specified already when you instantiate your class. Like var obj = new SomeGeneric<DateTime>();. So it should be something that logically "belongs" to the object modelled by the class.
If your method is static, and you choose to make the class generic, you will still have to specify the type parameter together with the class somehow. If the method is called from outside the class, it would go like SomeGeneric<DateTime>.Swap(ref a, ref b);.
The advantage with making the method generic, is that in many cases you can use type inference which allows you to omit the angle bracketed type parameter. You can only do this with generic methods. Example: nonGeneric.Swap(ref a, ref b); where the Swap<T> method is generic. The compiler will look at the compile-time types of a and b and figure out which T fits in, without you specifying it.
Conclusion: If the T does not logically belong to the class (as in List<T>), put it with the method.
Here's one example where generic methods really shine. Consider an expression such as 1+2 expressed as a binary tree. You want to implement the Visitor pattern on the entire tree, with the goal being some sort of map/reduce operations. Some examples would be:
Reducing an expression to a string to print it
Reducing an expression to a double to calculate its value
Mapping an expression to another expression with some members altered/added/removed
All of these operations can be put behind a Visitor pattern method:
public abstract class Expression
{
public abstract T Reduce<T>(ITransformer<T> transformer);
}
This is similar to the classic Visitor implementation, but the terminology is changed: we have Reduce() instead of Accept() and an ITransformer<T> instead of an IVisitor. Notice that the method is generic.
This approach allows us to create any number of ITransformer<T> classes that transform the hierarchy to any type T, supporting map-reduce operations.
Is there a way to use a collection of a generic class, without supplying the underlying type ?
Let's explain :
Here is what I'd like to have :
class TimeSerie<TValue> {
enter code here
}
List<TimeSerie<?>> blah;
Here is what I have to do so far :
class TimeSerie {}
class TypedTimeSerie<TValue> : TimeSerie {}
List<TimeSerie> blah;
So, any way to use the nice first solution ? (although I guess it would raise problems when trying to cast, for a loop for example ...)
You can make your using code generic too... but at some point you do have to specify the type argument. You're not going to be able to create an instance of the generic type without the type argument being known. You can provide that information at execution time using reflection if you must, but it has to be there somehow.
I dont see based on your question why you cannot derive your custom collection from ICollection<T> or List<T> (or maybe derive from ICollection and delegate the calls to a field of type List<T> you store internally?
(It's entirely possible I'm just not getting it, but can you give a small bit more sample code?)
Why not ?
List<TimeSerie<Object>> blah;
Then after you specify your object. Also define your base class accordingly.
Note that some 'mumbling' is possible in relation to anonymous types with c# thanks to two things:
Type inference
unification of identical anonymous types
If you are happy to rely on these two things remaining fixed (there are no guarantees on this, especially in relation to 2) then the following may be useful.
public static class Mumble
{
public static HashSet<T> HashSet<T>(T prototype)
{
return new HashSet<T>();
}
public static List<T> List<T>(T prototype)
{
return new List<T>();
}
}
You can use it like so:
var set = MumbleSet(new { Foo="", Bar="", Baz=0 });
var list = MumbleList(new { Foo="", Bar="", Baz=0 });
set.Add(new { Foo="x", Bar="y", Baz=1 });
set.Add(new { Foo="a", Bar="b", Baz=1 });
list.Add(new { Foo="a", Bar="b", Baz=1 });
var intersection = list.Intersect(set);
var concat = list.Concat(set);
This works well in cases where you have anonymous types you wish to populate into some other collection for use elsewhere within a method. A common use would be reading from a database query into a set for latter checking for existence within a loop where expressing this as a series of linq queries was either too cumbersome or too expensive.
For your motivating example you would have to add the following:
class TimeSerie<TValue>
{
// or some other constructor equivalent
public TimeSerie(TValue value) { /* assign the value */ }
}
static class TimeSerieMumble
{
public static TimeSerie<TValue> New<TValue>(TValue value)
{
return new TimeSerie<TValue>(value);
}
}
Then you could use the code like so:
var tsList = Mumble.List(TimeSerieMumble.New(new { Name="", Value=0 }));
foreach (var x in from c select new { c.Name, c.Value })
{
tsList.Add(TimeSerieMumble.New(new { x.Name, x.Value }));
}
Mumbling which 'leaks' into the public api is not feasible in c# 3.5 unless the type is to be mumbled through a series of type inferred generic methods in the same way as the above example. I have never seen a case where such a thing was useful given the resulting contortions required to the calling code. I would not think it would improve readability either. As a rule of thumb using more than the two levels of mumbling in the Name/Value example is likely to lead to serious complications down the line.
As others have said, there's no easy way to do this in C#.
However, if it's really important, it is possible to faithfully encode this pattern using a few extra types, although it's a bit ugly:
interface ITimeSeriesUser<X> {
X Use<T>(TimeSeries<T> series);
}
interface ITimeSeriesUser {
void Use<T>(TimeSeries<T> series);
}
interface ITimeSeries {
X Apply<X>(ITimeSeriesUser<X> user);
void Apply(ITimeSeriesUser user);
}
class TimeSeries<T> : ITimeSeries {
X Apply<X>(ITimeSeriesUser<X> user) { return user.Use(this); }
void Apply(ITimeSeriesUser user) { return user.Use(this); }
/* Your existing code goes here */
}
Now you can create a List<ITimeSeries> instance which holds TimeSeries<T>
values regardless of their type arguments, and you can use ITimeSeriesUser
implementations to manipulate them. Obviously this requires quite a bit of boilerplate,
but if you need a faithful way to express the concept of a TimeSeries<?> then this may be your best bet.