[英]Visual Studio Intellisense not showing methods on generic overload
[英]Visual Studio 2015 Intellisense fails to determine types of lambdas in some generic methods
Visual Studio 2015无法确定Enumerable.Join
等方法中的lambda参数类型。 请考虑以下代码:
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 });
}
当我输入book => book.
没有出现。 当我将鼠标悬停在book
,Intellisense标记它(parameter) ? book
(parameter) ? book
。
devenv.exe /resetuserdata
Func<>
和Expression<Func<>>
同样发生 books.Select(book => book.
正常工作。 Book
并给了我正确的选项。 这导致了一个有趣的解决方法,我可以在其中输入books.Join(authors, , , )
,然后填写空白并再次获得智能感知。 Wrapper<Book>.Combine(authors, book => book.AuthorId, author => author.Id
适用于book
但不适用于author
。 book
的类型来自类的泛型参数,但author
的类型来自方法的。 Join
有多个覆盖,但问题发生在下面的本土示例中没有覆盖。 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);
}
}
以下是当您尝试编写代码并依赖于泛型类型的智能感知解释时,智能感知可能发生的情况的解释,以及确定在编写book => book.
时要提供的类选项book => book.
或者author => author.
。
1。
public void Combine<TOuter, TKey>(Wrapper<TOuter> outer, Func<TInner, TKey> innerKey, Func<TOuter, TKey> outerKey) {}
//Intellisense fails on 'author => author.Id' but works for the book lambda.
books.Combine(authors, book => book.AuthorId, author => author.Id);
这里,作为参数传递给查询的TKey是book类型,与TOuter匹配。 所以作者会失败。
2。
public void ThisWorks<TOuter>(Wrapper<TOuter> outer, Func<TInner, int> innerKey, Func<TOuter, int> outerKey){}
//Intellisense works perfectly here.
books.ThisWorks(authors, book => book.AuthorId, author => author.Id);
这是有道理的,因为有一种类型作为参数传递给查询书籍,然后其中的每个函数都使用它的参数类型传递,并且它是相应的密钥。
3。
public static void CombineExt<TInner, TOuter, TKey>(this Wrapper<TInner> inner, Wrapper<TOuter> outer,
Func<TInner, TKey> innerKey, Func<TOuter, TKey> outerKey) {}
//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);
在这里我不确定,但不清楚TKey被分配给什么类型,书籍或作者。
4。
public static void ThisAlmostWorks<TInner, TOuter>(this Wrapper<TInner> inner, Wrapper<TOuter> outer,
Func<TInner, int> innerKey, Func<TOuter, int> outerKey) { }
//Intellisense fails on 'book => book.AuthorId' but works for 'author => author.Id'
books.ThisAlmostWorks(authors, book => book.AuthorId, author => author.Id);
在这里,我怀疑你用this Wrapper
覆盖了Type,所以它正在使用作者。
对于你的var测试:
IEnumerable<Book> books = null;
IEnumerable<Author> authors = null;
您从列表中选择为空,因此它们都会失败。 尝试初始化它们,就像在进一步的代码中一样。
对于现实生活代码:
然后将AuthorId更改为Author。 您需要能够从两个表中进行选择。 就个人而言,我发现这是一种更简单的方法来处理绑定,使用模型视图和在数据库上运行查询。
public class Book
{
public Author Author { 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;
var books_ = from book in books
select book;
var books = books.Include(book => book.Author);
books_ = books_.Where(book => book.Author.Id, // to do.
对于创建新对象,我不会通过像这样的链接查询来执行此操作。 作者要么存在,要么需要创建,可以创建书籍,既可以添加Author Author
,也可以使用int AuthorId
。
Book类还需要一个ID作为功能数据库。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.