如何正确翻译" VAR" lambda表达式到具体类型的结果呢? [英] How to properly translate the "var" result of a lambda expression to a concrete type?

查看:189
本文介绍了如何正确翻译" VAR" lambda表达式到具体类型的结果呢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我想更多地了解lambda表达式。我读这个问题计算器上,同意选择的答案,并试图实现使用在C#控制台应用程序使用一个简单的LINQ表达式的算法。



我的问题是:我怎么了lambda表达式的VAR结果翻译成可用的对象,然后我就可以打印结果?



我也明白发生了什么事的深入的解释,当我宣布外=> outer.Value.Frequency



(我读过lambda表达式的众多解释,但进一步的澄清将帮助)

  C#
//输入:{5,13,6,5,13,7,8,6,5}

//输出:{5,5,5,13,13,6,6,7,8}

//现在的问题是在递减的顺序来排列阵列中的数字它们的频率,并保持其发生的顺序。

//如果在13和6之间的这种例子的领带,等等,然后输入数组中第一次出现的数目将是第一位的输出数组中为止。

名单,LT; INT>输入=新的List< INT>();
input.Add(5);
input.Add(13);
input.Add(6);
input.Add(5);
input.Add(13);
input.Add(7);
input.Add(8);
input.Add(6);
input.Add(5);

&字典LT; INT,FrequencyAndValue>词典=新词典< INT,FrequencyAndValue>();

的foreach(在输入整型数字)
{
如果(!dictionary.ContainsKey(数字))
{
dictionary.Add(数字,新FrequencyAndValue(1,数));
}
,否则
{
辞典[数字]。频率++;
}
}

VAR的结果= dictionary.OrderByDescending(外=> outer.Value.Frequency);

//如何,结果弄成我可以打印翻译?

有关答案完整的打印命令,看到的我的回答这里


解决方案

我怎么了lambda表达式的VAR结果翻译成可用的对象,我可以然后打印出结果?




首先,在λ表达是指具有以下形式 A的表达的只有部= GT; b 。 。您的查询的其余部分只是一个方法调用了一个lambda作为参数



无论如何,如果我可以教人们了解LINQ一件事情会是这样:结果不是查询的结果的,它的是查询本身的。



如果你想看到的结果,要求每个结果查询:

 的foreach(在结果VAR项)
Console.WriteLine(item.ToString());




我也体会到正在发生的事情时,进行了深入的解释我宣布外=> outer.Value.Frequency




当然。首先,我们制定的各类涉及的一切。我们看到,在lambda是一个函数,它接受一个KeyValuePair,并返回一个int,所以我们产生的方法

 静态私人诠释MyLambda (KeyValuePair< INT,FrequencyAndValue>外)
{
返回outer.Value.Frequency;
}



下一步,我们采取的方法,并创建一个代表出来的:

  VAR的结果= dictionary.OrderByDescending(
新Func键< KeyValuePair< INT,FrequencyAndValue>中INT>(MyLambda));

和重写扩展方法调用:

  VAR的结果= Enumerable.OrderByDescending< KeyValuePair< INT,FrequencyAndValue>中INT>(
字典,
新Func键< KeyValuePair< INT,FrequencyAndValue>中INT>( MyLambda));

和重写VAR:

  IOrderedEnumerable< KeyValuePair< INT,FrequencyAndValue>>结果= 
Enumerable.OrderByDescending< KeyValuePair< INT,FrequencyAndValue>中INT>(
字典,
新Func键< KeyValuePair< INT,FrequencyAndValue>中INT>(MyLambda));



我希望你能同意你键入的代码是一大堆比这个烂摊子更易读。类型推断的岩石。



结果是代表由给定的密钥进行排序本词典的能力的对象。阅读仔细:它代表的能力的排序由该密钥的字典。它实际上并没有这样做,直到你问的结果;到目前为止,它是一个对象,说当被问及对于结果,是用这种密钥字典。



假设你要的结果。它是如何计算排序列表?它要求字典每个元素。然后调用每一个元素,这还给一个整数上MyLambda,所以我们现在有一对字典的键 - 值对和整数。然后,它生成排序在该整数对的列表。然后双手出列表中的一个元素的时间,当你问他们。




我们看到的lambda是一个函数,需要一个KeyValuePair,并返回一个int? - 你怎么确定我没有看到它从方法的返回值,也没有在OrderByDescending(记录)




啊,我看的混乱;对教学的原因,我fibbed以上关于确切的整理了一下,其中的语义分析所得



如何我们做这个类型推断是C#的更微妙和有趣的部分之一。



下面是它如何工作的。



我们看到,OrderByDescending被声明为:

 静态IOrderedEnumerable< T> OrderByDescending< T,K>(
这IEnumerable的< T>序列,
Func键< T,K> keyExtractor)

和我们看到我们有这种方法潜在的呼叫:

  OrderByDescending(字典,O => o.Value.Frequency)

但我们不知道T和K的。因此,我们通过查看是不是一个lambda一切开始。你的字典工具的IEnumerable< KeyValuePair< INT,FrequencyOrValue>> ,所以我们开始说T可能是 KeyValuePair< INT,FrequencyOrValue>



在这一点上有没有别的,我们可以从东西不是lambda表达式,所以我们开始寻找在lambda表达式推断。我们看到,我们有一个lambda O => o.Value.Frequency 键,到目前为止,我们已经确定keyExtractor的类型是 Func键< KeyValuePair< ; INT,FrequencyOrValue>中K> ,我们仍在寻找K.所以我们说假设拉姆达实际上是:

 (KeyValuePair< INT,FrequencyOrValue≠0)=> {返回o.Value.Frequency;} 

和我们要求的它绑定的?是!是的是的。我们可以成功编译此拉姆达没有错误,当我们这样做,我们可以看到,所有的收益报表返回一个int。



因此,我们推断,K是int和我们现在整个事情全类型的分析。



这是一个相当简单的推论;他们可以得到更离奇。看到我的博客的类型推断存档,如果这个问题特别感兴趣。



http://blogs.msdn.com/ericlippert/archive/tags/Type+Inference/default.aspx



在特定的,这里是我的一个视频上面的解释再加上一些其他有趣的情况下,东东:



http://blogs.msdn.com/ericlippert/archive/2006/11/17/a-face-made-for -email部分-three.aspx


So I'm trying to learn more about lambda expressions. I read this question on stackoverflow, concurred with the chosen answer, and have attempted to implement the algorithm using a console app in C# using a simple LINQ expression.

My question is: how do I translate the "var result" of the lambda expression into a usable object that I can then print the result?

I would also appreciate an in-depth explanation of what is happening when I declare the outer => outer.Value.Frequency

(I've read numerous explanations of lambda expressions but additional clarification would help)

C#
//Input : {5, 13, 6, 5, 13, 7, 8, 6, 5}

//Output : {5, 5, 5, 13, 13, 6, 6, 7, 8}

//The question is to arrange the numbers in the array in decreasing order of their frequency, preserving the order of their occurrence.

//If there is a tie, like in this example between 13 and 6, then the number occurring first in the input array would come first in the output array.

      List<int> input = new List<int>();
      input.Add(5);
      input.Add(13);
      input.Add(6);
      input.Add(5);
      input.Add(13);
      input.Add(7);
      input.Add(8);
      input.Add(6);
      input.Add(5);      

      Dictionary<int, FrequencyAndValue> dictionary = new Dictionary<int, FrequencyAndValue>();

      foreach (int number in input)
      {
        if (!dictionary.ContainsKey(number))
        {
          dictionary.Add(number, new FrequencyAndValue(1, number) );
        }
        else
        {
          dictionary[number].Frequency++;
        }
      }

      var result = dictionary.OrderByDescending(outer => outer.Value.Frequency);

      // How to translate the result into something I can print?? 

For the answer complete with print commands, see my answer here.

解决方案

how do I translate the "var result" of the lambda expression into a usable object that I can then print the result?

First off, the "lambda expression" is only the portion of the expression that is of the form a=>b. The rest of your query is just a method call that takes a lambda as its argument.

Anyway, if I could teach people one thing about LINQ it would be this: "result" isn't the results of the query, it is the query itself.

If you want to see the results, ask the query for each result:

foreach(var item in result)
    Console.WriteLine(item.ToString());

I would also appreciate an in-depth explanation of what is happening when I declare the outer => outer.Value.Frequency

Sure. We begin by working out the types of everything involved. We see that the lambda is a function which takes a KeyValuePair and returns an int, so we generate a method

static private int MyLambda(KeyValuePair<int, FrequencyAndValue> outer)
{
    return outer.Value.Frequency;
}

Next we take that method and create a delegate out of it:

var result = dictionary.OrderByDescending(
    new Func<KeyValuePair<int, FrequencyAndValue>, int>(MyLambda));

and rewrite the extension method call:

var result = Enumerable.OrderByDescending<KeyValuePair<int, FrequencyAndValue>, int>(
    dictionary,
    new Func<KeyValuePair<int, FrequencyAndValue>, int>(MyLambda));

and rewrite the var:

IOrderedEnumerable<KeyValuePair<int, FrequencyAndValue>> result =
    Enumerable.OrderByDescending<KeyValuePair<int, FrequencyAndValue>, int>(
    dictionary,
    new Func<KeyValuePair<int, FrequencyAndValue>, int>(MyLambda));

I hope you agree that the code you typed in is a whole lot more readable than this mess. Type inference rocks.

The result is an object which represents the ability to sort this dictionary by the given key. Read that carefully: it represents the ability to sort the dictionary by that key. It does not actually do that until you ask for a result; so far, all it is is an object that says "when asked for a result, sort the dictionary by this key".

Suppose you ask for a result. How does it compute the sorted list? It asks the dictionary for each element. Then it calls MyLambda on each element, which gives back an integer, so we now have a pair of dictionary key-value pairs and integers. It then builds a list of pairs sorted on that integer. Then it hands out elements of that list one at a time, as you ask for them.

We see that the lambda is a function which takes a KeyValuePair and returns an int" - How did you determine that? I don't see it from the method return value, nor documented in the OrderByDescending().

Ah, I see the confusion; for pedagogic reasons I fibbed a bit above regarding the exact order in which the semantic analysis proceeds.

How we do this type inference is one of the more subtle and interesting parts of C#.

Here's how it works.

We see that OrderByDescending is declared as:

static IOrderedEnumerable<T> OrderByDescending<T, K>(
    this IEnumerable<T> sequence, 
    Func<T, K> keyExtractor)

and we see we have a potential call to this method:

OrderByDescending(dictionary, o=>o.Value.Frequency)

But we do not know what T and K are. So we start by looking at everything that is NOT a lambda. Your dictionary implements IEnumerable<KeyValuePair<int, FrequencyOrValue>> so we start by saying "T is probably KeyValuePair<int, FrequencyOrValue>".

At this point there is nothing else we can deduce from stuff that is not lambdas so we start looking at the lambdas. We see that we have a lambda o=>o.Value.Frequency and so far we have determined that the type of keyExtractor is Func<KeyValuePair<int, FrequencyOrValue>, K> and we are still looking for K. So we say suppose the lambda actually was:

(KeyValuePair<int, FrequencyOrValue> o)=>{return o.Value.Frequency;}

And we ask does it bind? YES! Yes it does. We can successfully compile this lambda without error and when we do so, we see that all of its return statements return an int.

Therefore we deduce that K is int, and we now have a full type analysis of the whole thing.

This is a fairly straightforward inference; they can get much weirder. See the "type inference" archive on my blog if this subject particularly interests you.

http://blogs.msdn.com/ericlippert/archive/tags/Type+Inference/default.aspx

In particular, here's a video of me explaining the stuff above plus a few other interesting cases:

http://blogs.msdn.com/ericlippert/archive/2006/11/17/a-face-made-for-email-part-three.aspx

这篇关于如何正确翻译&QUOT; VAR&QUOT; lambda表达式到具体类型的结果呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆