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 /resetuserdataFunc<> 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