Please see further down for major update!
I have some code like this:
void Test(IEnumerable x) { var dynX = x.Cast<dynamic>(); var result = dynX.Select(_ => _.Text); }
in an existing library project targeted at .NET 4.5. VS2015’s IntelliSense underlines the Text
part, complaining that: 'object' does not contain a definition for 'Text'...
Sure enough, compiling fails with
error CS1061: 'object' does not contain a definition for 'Text' and no extension method 'Text' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)
This message always says 'object'
, even when I change the cast to .Cast<IAsyncResult>()
or whatnot. When I hover the lambda parameter, the tooltip shows it’s of type IColumn
(which exists but is unrelated). Again, no matter what type I cast to.
However, when I hover the Select()
method, it correctly shows the parameter as Func<dynamic, dynamic>
. If I specify the lambda parameter type explicitly, it compiles. If I specify the type parameters on Select()
explicitly, it works, too.
Other usages of LINQ with dynamic
are working. When I copy this method to another (existing) project in the solution, it compiles, too. When I copy it to another file in the same project, it does not compile.
It compiles with VS2013, too.
The very same error appears for all my colleagues as well, both in Windows 8.1 and Windows 10.
Perhaps this is some odd problem with type inference...?
Things I’ve tried that didn’t help:
Update
Well, I managed to create a self-contained minimal failing example:
static class Program { static void Main(string[] args) { IEnumerable x = new object[0]; IEnumerable<dynamic> dynX = x.Cast<dynamic>(); // CS1061 'object' does not contain a definition for 'Text'... // var tooltip shows IColumn instead of IEnumerable<dynamic> var result = dynX.Select(_ => _.Text); } public static IColumn Select<TResult>(this IColumn source, Func<object, TResult> selector) { throw new NotImplementedException(); } } public interface IColumn { }
From how I see it, this clearly indicates there’s a serious bug in how VS2015/the new compiler version resolves extension methods.
The following is only loosely related and is mainly about misleading error messages. I decided to leave it to not make comments confusing.
Even worse, these also fail with the same error, even though neither IEnumerable
nor object
could possibly have an extension method Select()
:
// CS1061 'object' does not contain a definition for 'Text' // var tooltip shows IColumn var result2 = x.Select(_ => _.Text); object o = new object(); // CS1061 'object' does not contain a definition for 'Text' // var tooltip shows IColumn var result3 = o.Select(_ => _.Text);
Addendum
This issue is now tracked on the Roslyn bug tracker.
cant speak to why it works in one VS and not the Other but this is what i would do
rename.
public static IColumn Select<TResult>(this IColumn source, Func<object, TResult> selector) { throw new NotImplementedException(); }
"Select" is a build in Method Name for other common lib. so I highly suggest you rename it to something like "AppColumnSelectText" or what ever but not "Select".
then change
public interface IColumn { }
To
public interface IColumn { string Text {get; set;} }
then implement it
public class MyClass : IColumn { public string Text { get; set;} }
Then cast your dynamic to IColumn instead, assuming it come from MyClass class type
var columns = fields.Select(a => new {a as IColumn}).ToList();
Then your will be able to do
var result3 = columns.AppColumnSelectText(x => x.Text);
I know this is probably not what you are looking for but the programming is cleaner and you can archive the same result.
Please read the below and comments hopefully this paints a better picture.
public static class Test { public static IColumn Select<TResult>(this IColumn source, Func<object, TResult> selector) { throw new NotImplementedException(); } public static IColumn SelectOtherColumn<TResult>(this IColumn source, Func<IColumn, TResult> selector) { throw new NotImplementedException(); } } public interface IColumn { string Text { get; set; } } public class Program { private static void Main(string[] args) { IEnumerable ojb = new object[0]; IEnumerable<dynamic> dynX = ojb.Cast<dynamic>(); // CS1061 'object' does not contain a definition for 'Text'... // var tooltip shows IColumn instead of IEnumerable<dynamic> //NB this is the System.Linq.Select var result = dynX.Select(x => x.Text); var xzy = dynX as IColumn; //converstion here will probably FAIL so this makes this pointless. //here the compliter complains as the Type object has no Text Prop as it was not sepcified anywhere var theThingyouwant1 = xzy.Select(x => x.Text); //here you are OK as the complier can infer something var theThingyouwant2 = xzy.SelectOtherColumn(x => x.Text); } }
Update Further to this... See below for illustration perposes
public class MyType { public string Text { get; set; } public string SomethingEsle { get; set; } } public class Program { private static void Main(string[] args) { List<MyType> ojb = new List<MyType>(); ojb.Add(new MyType {Text = "OMG", SomethingEsle = "cat"}); //dynX is a dynamic... var dynX = ojb.Select(x => new {x.Text, x.SomethingEsle}).ToList(); //NB this is the System.Linq.Select //this now works as the complier can determine that there is a property Text var result = dynX.Select(x => x.Text).ToList(); } }
You could use your Select... but it only works on something which implements IColumn, which is why i find it hard to see how it would ever work.
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