相关疑难解决方法(0)

'闭包'和'lambda'有什么区别?

有人能解释一下吗 我理解它们背后的基本概念,但我经常看到它们互换使用,我感到困惑.

现在我们在这里,它们与常规功能有什么不同?

lambda closures functional-programming function

774
推荐指数
12
解决办法
12万
查看次数

为委托分配本地功能

在C#7.0中,您可以声明本地函数,即生活在另一个方法中的函数.这些本地函数可以访问周围方法的局部变量.由于局部变量仅在调用方法时存在,我想知道是否可以将一个局部函数分配给一个委托(它可以比这个方法调用寿命更长).

public static Func<int,int> AssignLocalFunctionToDelegate()
{
    int factor;

    // Local function
    int Triple(int x) => factor * x;

    factor = 3;
    return Triple;
}

public static void CallTriple()
{
    var func = AssignLocalFunctionToDelegate();
    int result = func(10);
    Console.WriteLine(result); // ==> 30
}
Run Code Online (Sandbox Code Playgroud)

它确实工作!

我的问题是:为什么这有效?这里发生了什么?

c# c#-7.0

13
推荐指数
2
解决办法
1504
查看次数

为什么lambda表达式在方法终止后保留封闭范围变量值?

我的印象是C#中的lambda表达式上下文包含对其中使用的父函数作用域的变量的引用.考虑:

public class Test
{
    private static System.Action<int> del;

    public static void test(){
        int i = 100500;
        del = a => System.Console.WriteLine("param = {0}, i = {1}", a, i);
        del(1);

        i = 10;
        del(1);

    }

    public static void Main()
    {
        test();
    }
}
Run Code Online (Sandbox Code Playgroud)

输出

param = 1, i = 100500
param = 1, i = 10
Run Code Online (Sandbox Code Playgroud)

但是,如果这是真的,则以下内容将是非法的,因为lambda上下文将引用超出范围的局部变量:

public class Test
{
    private static System.Action<int> del;

    public static void test(){
        int i = 100500;
        del = a => System.Console.WriteLine("param = {0}, …
Run Code Online (Sandbox Code Playgroud)

c# lambda

6
推荐指数
1
解决办法
822
查看次数

C#LINQ结果出现差异

当我这样做:

currentPage = metadataResponse.ApplicationType.Pages.Find(
   page => page.SortOrder == ++currentPage.SortOrder);
Run Code Online (Sandbox Code Playgroud)

值为currentPagenull.

但是同样的逻辑,当我将增量值赋给一个整数变量,然后尝试得到 currentPage

int sortOrder = ++currentPage.SortOrder;
currentPage = metadataResponse.ApplicationType.Pages.Find(
    page => page.SortOrder == sortOrder);
Run Code Online (Sandbox Code Playgroud)

currentPage 得到人口.

对于为什么一个有效而另一个无效,有没有人有一个很好的答案?

.net c#

5
推荐指数
1
解决办法
119
查看次数

将简单的lambda表达式或本地函数分配给委托的性能

当使用一个非常简单的表达式作为创建ILookup的键时,Enumerable.ToLookup<TSource,?TKey> Method (IEnumerable<TSource>,?Func<TSource,?TKey>)我可以使用lambda表达式:

var lk = myItems.ToLookup((x) => x.Name);
Run Code Online (Sandbox Code Playgroud)

或本地功能:

var lk = myItems.ToLookup(ByName);

string ByName(MyClass x)
{
     return x.Name;
}
Run Code Online (Sandbox Code Playgroud)

我很好奇这个简单案例是否存在差异.

Local函数vs Lambda C#7.0的回答中,SO用户svick给出了一个很好的论据 - 为什么-in general-局部函数比lambdas更好.

重要的一点是性能的差异:

创建lambda时,必须创建一个委托,在这种情况下这是一个不必要的分配.本地函数实际上只是函数,不需要代理.

但是因为ToLookup()无论如何我们都将它传递给了一个委托.性能还有差异吗?
我可以想象编译器必须为myItems.ToLookup的每次调用创建一个新的委托lambda,而本地方法只需要一个委托实例; 这是真的?

svick 答案中性能的第二个不同点是捕获变量和创建闭包:

此外,本地函数在捕获局部变量时更有效:lambdas通常将变量捕获到类中,而本地函数可以使用struct(使用ref传递),这又避免了分配.

然而,因为表达不从外部范围使用变量,也不必是封闭的陈述里德·科普塞扩大通过埃里克利珀在回答在C#闭包是Lambda表达式?:

lambda可以使用闭包来实现,但它本身不一定是闭包.- Reed Copsey
[...]
一个可以被视为对象的函数只是一个委托.使lambda成为闭包的原因是它捕获了它的外部变量.- Eric Lippert

这多少有些矛盾埃里克利珀自己是他的回答指定的本地函数来代表 埃里克利珀解释一个局部函数为命名的λ:

本地函数基本上只是一个带有关联名称的lambda.

但这是一个较小的技术细节和lambda/local函数的代表,它们捕获外部范围变量.

这个简单的表达式不是递归的,不是泛型的,也不是迭代器.看起来更好的是一个意见问题.
那么,简单的非捕获,非递归,非泛型和非迭代器lambda表达式和本地函数之间的性能(或其他)是否有任何差异?

c# lambda c#-7.0

5
推荐指数
1
解决办法
336
查看次数

推迟启动Task &lt;T&gt;

我有一系列方法(具有可变数量的参数)返回一个Task,我想通过传递Task来创建一个在每个方法之前和之后执行某些操作的方法。我简化了此示例中的所有内容(删除了cancelToken,实际处理等):

public async Task<string> GetDataString()
{
    Console.WriteLine("Executing");
    return "test";
}


public async Task<T> Process<T>(Task<T> task)
{
    Console.WriteLine("Before");
    var res = await task;
    Console.WriteLine("After");
    return res;
}
Run Code Online (Sandbox Code Playgroud)

而在我的主要:

Task<string> task = GetDataString();
string result = await Process<string>(tasks);
Console.WriteLine(res);
Run Code Online (Sandbox Code Playgroud)

控制台输出是

Executing
Before
After
test
Run Code Online (Sandbox Code Playgroud)

我该怎么做才能创建任务而不实际启动它?并仅在等待之前启动它?

我设法通过创建PauseToken来做到这一点,如本文所述:https ://devblogs.microsoft.com/pfxteam/cooperatively-pausing-async-methods/ 但我想知道是否有更好的方法。

谢谢,Mattia

c# task-parallel-library async-await .net-core

5
推荐指数
1
解决办法
69
查看次数

C#通过for循环插入数组值

大家好

我想要做的是调用“FillDeck”方法来用 52 个数组元素填充“deck []”。for 循环用于添加元素 - 出于测试目的,它只是添加来自 for 循环的 y+x 值。我所做的是使用变量“placement”来指示我的索引位置,然后增加放置变量,因此对于每次循环迭代,索引都会增加,从而向该特定索引添加一个数组元素。但是,我得到了 IndexOutOfRangeException,这是我想弄清楚的。

注意:我不能自动为数组使用预先确定的值,我必须调用一个方法,该方法的目的是将值添加到数组中。由于它是具有嵌套 for 循环的卡片组来确定等级/花色,因此这是解决此问题的好方法。

谢谢=)

    static void Main(string[] args)
    {
        int [] deck = {};
        FillDeck(deck); // Error Here
    }
    public static void FillDeck(int[] deck)
    {
        int placement = 0;
        // 0 = Ace , 12 = King : 0 = Hearts, 1 = Diamonds, 2 = Clubs, 3 = Spades
        for (int x = 0; x < 13; x++)
            for (int y = 0; x < 4; …
Run Code Online (Sandbox Code Playgroud)

c#

2
推荐指数
1
解决办法
1万
查看次数

Parallel.ForEach - 具有嵌套实例对象的线程安全性

在这种情况下,Employee和/或Illness实例是否是线程安全的?每个线程都有自己的对象副本吗?最初我认为每个线程都有自己的副本,但现在我不确定.

Parallel.ForEach(line01s, _options, o =>
{
    var employee = new Employee();
    // set values on employee...Safe?

    var illness = new Illness();
    // set values on illness...Safe?

    employee.AddIllness(illness);  // Illness is a property on Employee

}
Run Code Online (Sandbox Code Playgroud)

是否可以在错误的Employee对象上设置Illness对象?我是否需要在employee.AddIllness(疾病)周围添加锁定; ?我使用这个TPL的东西越多,我发现我就越不理解

c# task-parallel-library

2
推荐指数
1
解决办法
1161
查看次数

如何将多个方法(带参数)作为参数传递?

假设我有以下WCF代码:

  try
  {
       ServiceClient proxy = new ServiceClient();
       proxy.ClientCredentials.UserName.UserName = "user";
       proxy.ClientCredentials.UserName.Password = "password";
       proxy.GetData(2);
       if (proxy.State = CommunicationState.Opened)
       {
           proxy.GetData("data");
       }
       proxy.Close();
  }
  catch (FaultException ex)
  {
      // handle the exception      
  }
Run Code Online (Sandbox Code Playgroud)

而且因为我注意到try ... catch和其他逻辑是重复的,更不用说设置WCF调用是昂贵的,我想向这个函数发送许多"方法和参数".

本质上是传递GetData(2)GetData("data")作为方法数组,并使结果异步或同步返回.

我怎么做到这一点?

我想我可以有两个'ref'对象来处理结果[]和对结果[]的共享锁.但是我不确定如何将"带参数的方法"作为参数传递给另一个函数.

也许另一种看待它的方法可能是一个函数指针数组,使用不同的参数来表示相同的函数.

任何人都可以推动我做正确的方法吗?

更多信息:

我问这个问题所以我可以优化这种方法来处理WCF异常和重试,但所以我不必总是在每次调用后打开/关闭客户端.

c# performance wcf delegates closures

1
推荐指数
1
解决办法
982
查看次数