Implicit conversion from IEnumerable<int> to IEnumerable<dynamic> - c#

I haven't used dynamic much in C# so far, so I came across a (small) problem when trying to create a simple WebGrid-like component for learning purposes.
The normal WebGrid takes as its data source an IEnumerable<dynamic>, so I emulated that. Then I created a view like the following:
#model IEnumerable<int>
#{
MyWebGrid grid = new MyWebGrid(Model);
}
In the MVC project, this leads to a runtime conversion error, so I created a small console application (this doesn't compile of course):
class Program
{
class Foo { public int Id { get; } }
static void Main()
{
CheckConversion(new List<int>().AsEnumerable()); // Error
CheckConversion(new List<Foo>()); // works
int x = 5;
CheckSingleParameterConversion(x); // works
}
private static void CheckConversion(IEnumerable<dynamic> source) { }
private static void CheckSingleParameterConversion(dynamic val) { }
}
The error (in short): Cannot convert from IEnumerable<int> to IEnumerable<dynamic>.
What is the exact reasoning behind these differing behaviors? I know that dynamic is a reference type and could thus understand why there might be some problem with the IEnumerable<int> here, but why does it work in the single parameter case then?

Problem is not in dynamic itself, it's all about variance.
As said in MSDN
Variance applies only to reference types; if you specify a value type
for a variant type parameter, that type parameter is invariant for the
resulting constructed type.
So IEnumerable<int> cannot be casted to IEnumerable<dynamic>, because int is a value type and dynamic is just an object marked with special attribute.

Related

Unable to cast '<T>d__14`1[System.Object] to 'IEnumerable`1[System.Int32]'

I'm trying to create generator of IEnumerable to set School.Foundation,
this is the Type that I'm trying to populate at the moment:
public class School
{
public IEnumerable<int> Foundation;
}
this is my generator so far:
public static IEnumerable<T> GetEnumerable <T>(Func<T> f)
{
while(true)
{
yield return f();
}
}
So what I'm doing is the following reflection:
Dictionary<string, Func<object>> funcMembers;
public static object Generator(String name, Type t)
{
Func<object> func;
if (funcMembers.TryGetValue(name, out func))
{
if (t.Name.StartsWith("IEnumerable"))
return GetEnumerable(func);
}
}
I made the following test to check if it was fully functional:
[TestMethod]
public void Test_generator()
{
private Dictionary<string, Func<object>> funcMembers = new Dictionary<string, Func<object>>();
//adding the Field "Foundation" generator on the dictionary
funcMembers.Add("Foundation", () => {return 4;});
School s = new School();
// calling my Generator that should return IEnumerable<int>
s.Foundation = Generator(
"Foundation",
typeof(School).GetField("Foundation").
Assert.IsNotNull(s.Foundation);
}
i have the following error when I'm on line:
s.Foundation = Generator(
"Foundation",
typeof(School).GetField("Foundation").
the error is the following:
> Unable to cast object of type '<GetEnumerable>d__14`1[System.Object]'
> to type 'System.Collections.Generic.IEnumerable`1[System.Int32]'.
Your funcMembers contain this:
funcMembers.Add("Foundation", () => {return 4;});
the right-hand-side is an anonymous delegate, parameterless, returning constant 4. It is implicitely typed as Func<object> soit can be added to the dictionary. As all delegates, compiler compiles it as a class, but since it doesn't have name, a special name of "d__14`1[System.Object]" is automatically generated.
Then, it seems that either Generator or GetEnumerable method return this delegate object directly, instead of invoking it and getting the value of 4 and wrapping it into IEnumerable.
This delegate returned from Generator or GetEnumerable is then assigned to s.Foundation, which causes this error you noticed (since the anonymous class of the delegate obviously doesn't implement IEnumerable).
I bet you can see all of that simply by stepping with the debugger.For a better view, write it like that:
var tmp = Generator(
"Foundation",
typeof(School).GetField("Foundation")...
s.Foundation = tmp;
and observe the value in TMP and then, well, diagnose what's up (ie. by stepping into Generator and seeing what happens there) and fix it.
Side note: This is as far as got with these code scraps you pasted. I can't tell you more about your problem, because the code you provided contains severe errors (i.e Generator - not all code paths return value), some lines are incomplete (where's the end of typeof(School).GetField("Foundation").?) and so on.
In such cases, please try to provide minimal complete example which actually compiles.

Unpredictible behaviour in c# dynamic

I've found a bug (feature?) during learning dynamic in C#. Can anyone explain me, why do I have an exception??
static class Program
{
public static void Main(string[] args)
{
dynamic someObj = ConstructSomeObj((Action)(() => Console.WriteLine("wtf")));
var executer = someObj.Execute;
executer(); // shows "wtf"
someObj.Execute(); // throws RuntimeBinderException
Console.ReadKey();
}
static dynamic ConstructSomeObj(dynamic param)
=> new { Execute = param };
}
Note: typeof both exectuer and someObj is dynamic
Let's look at following code:
using System;
using System.Collections.Generic;
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("first");
// works perfectly!!!
dynamic foo = new { x=(Action)(() => Console.WriteLine("ok")) };
foo.x();
// fails
dynamic foo2 = new { x=(object)(Action)(() => Console.WriteLine("ok2")) };
foo2.x();
}
}
dynamic uses reflection to access objects method and fields and since it cannot know exact types it must rely on type information present in objects on which it operate.
When field x in anonymous type is properly typed as delegate invocation foo.x() works because dynamic can see that field value is delegate.
When you use
static dynamic ConstructSomeObj(dynamic param)
{ return new { x = param }; }
to create anonymous class you created class with field x of type object (dynamic is object behind the scenes). When you call obj.x dynamic sees that field type is an object and it does't bother to check to what exact type this field points. And since object doesn't have Invoke() method like delegates it throws exception. If you change method parameter type to Action it will work.
I guess this decision to check field type instead of type of value that field contains was taken to provide better performance. In other words when you check field type CallSite class generated by dynamic can be cached and reused later.
References:
https://github.com/mono/mono/blob/ef407901f8fdd9ed8c377dbec8123b5afb932ebb/mcs/class/Microsoft.CSharp/Microsoft.CSharp.RuntimeBinder/Binder.cs
https://github.com/mono/mono/blob/ef407901f8fdd9ed8c377dbec8123b5afb932ebb/mcs/class/Microsoft.CSharp/Microsoft.CSharp.RuntimeBinder/CSharpInvokeMemberBinder.cs
EDIT: Checked this on mono, can somebody verify on VS
ok, interesting. This 2 Lines would work:
Task.Run(someObj.Execute);
((Action)someObj.Execute)();
It seems that the compiler does accept the () for dynamic types always and at runtime the CLR only looks 'one level deep'. So you can help here by adding explicit cast or do the cast implicit with the Task.Run(). If this is a feature or a bug!? ... no idea ;-) ...

Generic method handles IEnumerable differently than generic type

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.

Array of different generics

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.

Open Delegate fails when trying to access Int or DateTime property

I have been testing out using delegates instead of reflection for some object sorting and it was working good for string properties, but if I try an Int (or DateTime) it fails and throws
Error binding to target method.
class Program
{
static void Main(string[] args)
{
var sample = new SampleClass() { Num = 13, Text = "Sample" };
Console.WriteLine(ReadProp(sample,"Text")); //Works
Console.WriteLine(ReadProp(sample, "classProp")); //Works
Console.WriteLine(ReadProp(sample, "Num")); //Throws 'Error binding to target method.'
}
//Use a Delegate to improve speed of accessing property instead of reflection
static object ReadProp(SampleClass obj, string propName)
{
var method = obj.GetType().GetProperty(propName).GetGetMethod();
var getForProp = (Func<SampleClass, object>)Delegate.CreateDelegate(typeof(Func<SampleClass, object>), null, method);
return getForProp(obj);
}
}
//A sample class for illustration purposes
class SampleClass
{
public string Text { get; set; }
public int Num { get; set; }
public SampleClass classProp { get; set; }
}
My question is: Why does it work for strings or other classes but not for Int or DateTime?
I can see that if I change my Func<SampleClass, object> to Func<SampleClass, int> it will then work for my Int but I expected object would work for both.
Why does it work for strings or other classes but not for Int or DateTime?
Because a method which returns an int isn't a method which returns an object reference. There has to be a boxing conversion - so something's got to do that, and Delegate.CreateDelegate is trying to provide a delegate which just invokes the delegate and returns the result, with no value conversion involved.
It's slightly painful to do, but basically I suspect you should either be building a Func with an appropriate return value and using that directly or you should go via a wrapper delegate which calls the "real" delegate and boxes the result.
(Note that in your sample code, you're creating the delegate each time, which is going to be no faster than reflection. Hopefully your real code is more sensible :)
If you look at this code from protobuf-csharp-port you'll see I've got a method to do exactly this - a lambda expression calls the strongly-typed delegate, and then uses the implicit conversion to object (boxing where necessary) to provide the value. You should be able to use something very similar. However, if you're sorting do you really want a Func<T, object>? If you use a strongly-typed delegate instead, you may be able to avoid all this boxing.

Categories

Resources