为什么不需要以下通用方法呼叫需要类型?

发布于 2024-10-29 01:03:06 字数 591 浏览 1 评论 0原文

抱歉 - 不确定更好的名称,如果您能想到更好的名称,请修改。

我正在尝试更多地了解 IEnumerable/collections/generics,我以为我已经有所收获,直到这个例子让我明白:

 var nums = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 10 };

 var result = FilterNums(nums, i => i % 2 != 0);

.....

public static IEnumerable<T1> FilterNums<T1>(IEnumerable<T1> numslist, Func<T1, bool> predicateDelegate)

.....

为什么调用会调用 FilterNums< /代码> 工作吗?如果我将其更改为 FilterNums,它仍然有效,这就是我实际期望输入的内容。

那么,是如何检测 lambda 查询的 T1 而不需要我编写它还是发生了其他事情?

Sorry - not sure of a better name, please modify if you can think of better.

I am trying to learn a bit more about IEnumerable/collections/generics and I thought I was getting somewhere, until this example got me:

 var nums = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 10 };

 var result = FilterNums(nums, i => i % 2 != 0);

.....

public static IEnumerable<T1> FilterNums<T1>(IEnumerable<T1> numslist, Func<T1, bool> predicateDelegate)

.....

Why does the call the call to FilterNums work? If I change it to FilterNums<int>, it still works and that is what I actually expected to type.

So, is it some how detecting the T1 for the lambda query and not requiring me to write it or is something else going on?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

陌生 2024-11-05 01:03:06

类型推断过程有点复杂;有关详细信息,请参阅 C# 规范第 7 章。

简而言之,它的工作原理如下。

当您调用没有通用参数列表的方法时,首先我们创建一组该名称的所有可访问方法。

接下来我们检查它们是否是通用的。如果是,那么我们尝试看看是否可以从实际参数推断出泛型类型参数。推理过程是这样的。假设您有一个参数列表 A:

A: (nums, i => i%2 != 0)

和一个形式参数类型列表 P:

P: (IEnumerable<T1>, Func<T1, bool>)

以及一组泛型类型参数 X:

X: <T1>

类型推断的目标是从 A 的每个成员到 P 的相应成员进行推断,以便推导出关于 X 的每个成员的足够信息。

这个特殊问题很简单。从第一个参数我们可以看出nums的类型是int[]。我们看到 P 中的第一个形参是 IEnumerable。我们知道 int[] 可转换为 IEnumerable,因此 T1 可能是 int。我们记录了这一事实。

到这里,我们就基本完成了。我们没有任何关于 T1 的信息可以从第二个自变量/参数对推断出来。类型推断成功,并确定
T1 是整数。因此,我们假设您使用 作为类型参数列表来调用它。

这是一个非常简单的类型推断问题。考虑一下这个:

A: (customers, c=>c.Name)
P: (IEnumerable<T>, Func<T, R>)
X: <T, R>

这是您在执行 customers.Select(c=>c.Name) 时遇到的问题。

我们该怎么办?从第一个参数我们推断出“客户实现了 IEnumerable,因此 T 可能是 Customer”。 在进行推导之后,我们可以说“因此 lambda 中的 c 是 Customer。因此,这是从 Customer 到 Customer.Name 的任何类型的 lambda。这是字符串。因此 R 是字符串”。

看看在这种情况下如何将一个推论链接到下一个推论;我们不能简单地“并行”进行推理,因为一个推理可能取决于另一个推理的结果。这些依赖项可能包含循环和其他奇怪的拓扑。我们如何通过依赖链取得进展的具体细节有点复杂;详细信息请参阅规格。

我们还必须处理为类型参数推导两个或多个界限的情况,以及这些界限是“上限”、“下限”还是“精确”。

如果您对这个主题感兴趣,我已经写了大量有关它的文章。请参阅

http://blogs.msdn.com/b/ericlippert/archive/tags/type+ inference/

有很多关于类型推断各个方面的文章,而不仅仅是泛型方法类型推断。有关我解释方法类型推断在 C# 3.0 中如何工作的视频,请参阅:

http://wm .microsoft.com/ms/msdn/visualcsharp/eric_lippert_2006_11/EricLippert01.wmv

The type inference process is a bit complicated; see chapter 7 of the C# spec for exact details.

Briefly it works like this.

When you invoke a method without a generic parameter list, first we make a set of all the accessible methods of that name.

Next we check to see if any of them are generic. If they are then we try to see if the generic type arguments can be inferred from the actual arguments. The inference process goes like this. Suppose you have an argument list A:

A: (nums, i => i%2 != 0)

and a list of formal parameter types P:

P: (IEnumerable<T1>, Func<T1, bool>)

and a set of generic type parameters X:

X: <T1>

The goal of type inference is to make inferences from every member of A to the corresponding member of P in order to deduce enough information about each member of X.

This particular problem is easy. From the first argument we see that the type of nums is int[]. We see that the first formal parameter in P is IEnumerable<T1>. We know that int[] is convertible to IEnumerable<int>, and therefore T1 might be int. We make a note of that fact.

And at this point, we're basically done. We have nothing about T1 that we can infer from the second argument/parameter pair. Type inference succeeds, and determines that
T1 is int. So we pretend that you called it with <int> as the type argument list.

That was a very simple type inference problem. Consider this one:

A: (customers, c=>c.Name)
P: (IEnumerable<T>, Func<T, R>)
X: <T, R>

This is the problem you get when you do customers.Select(c=>c.Name).

What do we do? From the first argument we deduce "customers implements IEnumerable<Customer>, therefore T is probably Customer". After making that deduction we can then say "c in the lambda is therefore Customer. Therefore this is a lambda from Customer to whatever the type of Customer.Name is. That's string. Therefore R is string".

See how in that case one inference had to be chained onto the next; we cannot simply do inference "in parallel" because one inference might depend on the results of another. Those dependencies can contain loops and other odd topologies. The exact details of how we make progress through that chain of dependencies is a bit complicated; see the spec for details.

We also have to deal with the case where two or more bounds are deduced for a type parameter, and whether those bounds are "upper", "lower" or "exact".

If this subject interests you, I've written about it extensively. See

http://blogs.msdn.com/b/ericlippert/archive/tags/type+inference/

for lots of articles on various aspects of type inference, not just generic method type inference. For a video of me explaining how method type inference works in C# 3.0, see:

http://wm.microsoft.com/ms/msdn/visualcsharp/eric_lippert_2006_11/EricLippert01.wmv

南城追梦 2024-11-05 01:03:06

这是因为类型推断。

编译器知道您正在发送 int,因此它隐式地将泛型类型设置为 int。如果您查看智能感知,您会看到您的通用类型设置为 int。

This is because of type inference.

The compiler understands that you're sending an int, so it implicitly sets the generic type to int. If you'll look in the intellisense you'll see your generic type is set as int.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文