有人能解释一下吗 我理解它们背后的基本概念,但我经常看到它们互换使用,我感到困惑.
现在我们在这里,它们与常规功能有什么不同?
在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#中的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) 当我这样做:
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 得到人口.
对于为什么一个有效而另一个无效,有没有人有一个很好的答案?
当使用一个非常简单的表达式作为创建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,而本地方法只需要一个委托实例; 这是真的?
此外,本地函数在捕获局部变量时更有效:lambdas通常将变量捕获到类中,而本地函数可以使用struct(使用ref传递),这又避免了分配.
然而,因为表达不从外部范围使用变量,也不必是封闭的陈述由里德·科普塞和扩大通过埃里克利珀在回答在C#闭包是Lambda表达式?:
lambda可以使用闭包来实现,但它本身不一定是闭包.- Reed Copsey
[...]
一个可以被视为对象的函数只是一个委托.使lambda成为闭包的原因是它捕获了它的外部变量.- Eric Lippert
这多少有些矛盾埃里克利珀自己是他的回答到指定的本地函数来代表 埃里克利珀解释一个局部函数为命名的λ:
本地函数基本上只是一个带有关联名称的lambda.
但这是一个较小的技术细节和lambda/local函数的代表,它们捕获外部范围变量.
这个简单的表达式不是递归的,不是泛型的,也不是迭代器.看起来更好的是一个意见问题.
那么,简单的非捕获,非递归,非泛型和非迭代器lambda表达式和本地函数之间的性能(或其他)是否有任何差异?
我有一系列方法(具有可变数量的参数)返回一个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
大家好
我想要做的是调用“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) 在这种情况下,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的东西越多,我发现我就越不理解
假设我有以下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异常和重试,但所以我不必总是在每次调用后打开/关闭客户端.