Considering the following (pointless, but it's for illustration purpose) test class :
public class Test
{
public IEnumerable<string> ToEnumerableStrsWontCompile(IEnumerable<dynamic> t)
{
return t.Select(x => ToStr(x));
}
public IEnumerable<string> ToEnumerableStrsWillCompile(IEnumerable<dynamic> t)
{
var res = new List<string>();
foreach (var d in t)
{
res.Add(ToStr(d));
}
return res;
}
public string ToStr(dynamic d)
{
return new string(d.GetType());
}
}
Why doesn't it compile with the following error, on t.Select(x => ToStr(x))
?
Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<dynamic>'
to 'System.Collections.Generic.IEnumerable<string>'. An explicit conversion
exists (are you missing a cast?)
No error on the second method.
The Dynamic LINQ library exposes a set of extension methods on IQueryable corresponding to the standard LINQ methods at Queryable, and which accept strings in a special syntax instead of expression trees.
And Dynamic Linq is actually composed from strings, therefore it is potentially prone to attack by injection. Obviously, the attacker will have to be aware of the fact that you are using DynamicLinq and could attack only preparing the data so it results in valid malicious Dynamic Linq query.
Select() takes each source element, transforms it, and returns a sequence of the transformed values.
I believe what happens here is that since the expression ToStr(x)
involves a dynamic
variable, the whole expression's result type is also dynamic
; that's why the compiler thinks that it has an IEnumerable<dynamic>
where it expects an IEnumerable<string>
.
public IEnumerable<string> ToEnumerableStrsWontCompile(IEnumerable<dynamic> t)
{
return t.Select(x => ToStr(x));
}
There are two ways you can fix this.
Use an explicit cast:
public IEnumerable<string> ToEnumerableStrsWontCompile(IEnumerable<dynamic> t)
{
return t.Select(x => (string)ToStr(x));
}
This tells the compiler that the result of the expression is definitely going to be a string, so we end up with an IEnumerable<string>
.
Replace the lambda with a method group:
public IEnumerable<string> ToEnumerableStrsWontCompile(IEnumerable<dynamic> t)
{
return t.Select(ToStr);
}
This way the compiler implicitly converts the method group expression to a lambda. Note that since there is no mention of the dynamic
variable x
in the expression, the type of its result can be immediately inferred to be string
because there is only one method to consider, and its return type is string
.
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