Visual Studio 2015 cannot determine the types of lambda parameters in methods such as Enumerable.Join
. Consider the following code:
public class Book
{
public int AuthorId { get; set; }
public string Title { get; set; }
}
public class Author
{
public int Id { get; set; }
public string Name { get; set; }
}
public static void NoIntellisenseInEnumerableJoin()
{
IEnumerable<Book> books = null;
IEnumerable<Author> authors = null;
//Intellisense fails on both 'book => book.AuthorId' and 'author => author.Id'
var test = books.Join(authors, book => book.AuthorId, author => author.Id, (book, author) => new { book, author });
}
When I type book => book.
, nothing comes up. When I hover over book
, Intellisense labels it (parameter) ? book
.
devenv.exe /resetuserdata
Func<>
and Expression<Func<>>
books.Select(book => book.
works correctly.Book
and gives me the correct options. This leads to an interesting work-around where I can type books.Join(authors, , , )
first, then fill in the blanks and get intellisense again.Wrapper<Book>.Combine(authors, book => book.AuthorId, author => author.Id
works for book
but not for author
. The type of book
comes from the class's generic argument, but the type of author
comes from the method's.Join
has multiple overrides, but the problem occurs in the home-grown example below with no overrides.public class Wrapper<TInner>
{
public void Combine<TOuter, TKey>(Wrapper<TOuter> outer, Func<TInner, TKey> innerKey, Func<TOuter, TKey> outerKey)
{ }
public void ThisWorks<TOuter>(Wrapper<TOuter> outer, Func<TInner, int> innerKey, Func<TOuter, int> outerKey)
{ }
}
public static class WrapperExtensions
{
public static void CombineExt<TInner, TOuter, TKey>(this Wrapper<TInner> inner, Wrapper<TOuter> outer,
Func<TInner, TKey> innerKey, Func<TOuter, TKey> outerKey)
{ }
public static void ThisAlmostWorks<TInner, TOuter>(this Wrapper<TInner> inner, Wrapper<TOuter> outer,
Func<TInner, int> innerKey, Func<TOuter, int> outerKey)
{ }
}
public static class NoIntellisenseExamples
{
public static void NoIntellisenseInSimplerCase()
{
var books = new Wrapper<Book>();
var authors = new Wrapper<Author>();
//Intellisense fails on 'author => author.Id' but works for the book lambda.
books.Combine(authors, book => book.AuthorId, author => author.Id);
new Wrapper<Book>().Combine<Author, int>(authors, book => book.AuthorId, author => author.Id);
//Intellisense fails on both 'book => book.AuthorId' and 'author => author.Id' in both of the following:
books.CombineExt(authors, book => book.AuthorId, author => author.Id);
WrapperExtensions.CombineExt(books, authors, book => book.AuthorId, author => author.Id);
//Intellisense works perfectly here.
books.ThisWorks(authors, book => book.AuthorId, author => author.Id);
//Intellisense fails on 'book => book.AuthorId' but works for 'author => author.Id'
books.ThisAlmostWorks(authors, book => book.AuthorId, author => author.Id);
}
}
I've tried typing out your first example and the same thing happened to me. I type book => book.
and get nothing:
A Completed Statement
Why this is happening, I don't know. I can only assume that it's something to do with the statement being incomplete because once the statement is complete, I can go back and delete the .AuthorId
and I then get intellisense on the book
variable:
A Workaround
It's not a great solution, but you can work around this problem by declaring the type of the variable in the lambda statement. When you do that, you should get intellisense:
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