请检查下面的代码示例:
public class Sample
{
public int counter { get; set; }
public string ID;
public void RunCount()
{
for (int i = 0; i < counter; i++)
{
Thread.Sleep(1000);
Console.WriteLine(this.ID + " : " + i.ToString());
}
}
}
class Test
{
static void Main()
{
Sample[] arrSample = new Sample[4];
for (int i = 0; i < arrSample.Length; i++)
{
arrSample[i] = new Sample();
arrSample[i].ID = "Sample-" + i.ToString();
arrSample[i].counter = 10;
}
foreach (Sample s in arrSample) …Run Code Online (Sandbox Code Playgroud) 我想试试看,这里发生了什么?编译器生成什么样的代码?
public static void vc()
{
var listActions = new List<Action>();
foreach (int i in Enumerable.Range(1, 10))
{
listActions.Add(() => Console.WriteLine(i));
}
foreach (Action action in listActions)
{
action();
}
}
static void Main(string[] args)
{
vc();
}
Run Code Online (Sandbox Code Playgroud)
输出: 10 10 .. 10
根据这个,ActionHelper的新实例会为每次迭代创建.那么在这种情况下,我认为它应该打印1..10.有人能给我一些编译器在这里做的伪代码吗?
谢谢.
fMethod是一个Action<Fruit>.
但是当fMethod调用时,参数始终是最后一个条目_Fruits.
怎么解决这个?
foreach(Fruit f in _Fruits)
{
field.Add(new Element(f.ToString(),delegate{fMethod(f);}));
}
Run Code Online (Sandbox Code Playgroud) 在页156,他有一个例子,清单5.13"捕获多个委托的多个变量实例".
List<ThreadStart> list = new List<ThreadStart>();
for(int index=0; index < 5; index++;)
{
int counter = index*10;
list.Add(delegate
{
Console.WriteLine(counter);
counter++;
}
);
}
foreach(ThreadStart t in list)
{
t();
}
list[0]();
list[0]();
list[0]();
list[1]();
Run Code Online (Sandbox Code Playgroud)
在此列表之后的解释中,他说"在这种情况下,每个委托实例都捕获了一个不同的变量."
我理解这一点很好,因为我理解每次你关闭一个变量时,编译器会生成IL,将其封装在一个新的类中,专门用于允许捕获该变量(实质上使它成为一个引用类型,以便它引用的值)不会被当前执行范围的堆栈框架破坏).
但后来他谈到了如果我们index直接捕获而不是创建counter变量会发生什么- "所有代表都会共享相同的变量".
这个我不明白.是不是index在同一范围内counter?为什么编译器也不会index为每个委托创建一个新实例?
注意:我想我在输入这个问题时想出来了,但我会在这里留下问题给后人.我认为答案index实际上是在不同的范围内counter.索引基本上是在for循环中"声明"...每次都是相同的变量.
看一下为for循环生成的IL ,它证明变量是在循环外声明的(length并且i是在for循环声明中声明的变量).
.locals init (
[0] int32 length,
[1] int32 …Run Code Online (Sandbox Code Playgroud) foreach(var category in categories) {
a.AddRange(_db.Articles.Where(c => c.Categories.Contains(category)));
}
Run Code Online (Sandbox Code Playgroud)
代码运行正常,但我category在lambda表达式中使用的引用中收到了关于"访问修改后的闭包"的警告.
问题:在这种情况下是否有任何后果的警告?
可能重复:
为什么在lambda表达式中使用迭代变量是不好的
为什么我会得到:"lambda表达式中的迭代变量可能会产生意外结果"?假设我有以下代码:
Dim writeAbleColumns As String() = {"IsSelected", "IsFeeExpense", "IsSubscriptionRedemption"}
With grid
For Each column As DataGridViewColumn In .Columns
column.ReadOnly = Not Array.Exists(writeAbleColumns, Function(arrElement) column.Name = arrElement)
Next
End With
Run Code Online (Sandbox Code Playgroud)
我收到警告:
Warning 1 Using the iteration variable in a lambda expression may have unexpected results. Instead, create a local variable within the loop and assign it the value of the iteration variable.
Run Code Online (Sandbox Code Playgroud)
我不明白为什么将我的代码更改为以下更改:
Dim writeAbleColumns As String() = {"IsSelected", "IsFeeExpense", "IsSubscriptionRedemption"}
With grid
For Each column As DataGridViewColumn In …Run Code Online (Sandbox Code Playgroud) resharper让我把它变成一个局部变量,写下"访问修改后的闭包"
if (filter != null)
{
if (filter.CityId != 0)
{
ads = ads.Where(x => x.Ad.CityId == filter.CityId);
}
if (filter.BusinesCategoryId != 0)
{
ads = ads.Where(x => x.BusinessCategoryId == filter.BusinesCategoryId);
}
}
Run Code Online (Sandbox Code Playgroud)
为什么局部变量过滤?
我遇到了Linq的一个奇怪的行为:有两个linq表达式可能看起来相同,我有不同的结果!如果我循环一次我得到相同的结果,但在上面它什么都没发现.
这是代码:
Dictionary<String, String> mainDico = new Dictionary<String, String>();
mainDico.Add("key1", "value1");
mainDico.Add("key2", "value2");
List<Dictionary<String, String>> ls = new List<Dictionary<String, String>>();
Dictionary<String, String> fistDico = new Dictionary<String, String>();
fistDico.Add("key1", "value1");
fistDico.Add("key2", "value2");
Dictionary<String, String> secondDico = new Dictionary<String, String>();
secondDico.Add("key1", "other");
secondDico.Add("key2", "other");
ls.Add(fistDico);
ls.Add(secondDico);
IEnumerable<Dictionary<String, String>> failQuery = from p in ls
select p;
IEnumerable<Dictionary<String, String>> successfulQuery = from p in ls
select p;
String[] items = new String[] { "key1","key2" }; // with one element it works
foreach (var …Run Code Online (Sandbox Code Playgroud) 演示代码有一些问题.
var values = new List<int>() { 100, 110, 120 };
var funcs = new List<Func<int>>();
foreach(var v in values)
funcs.Add( ()=>v );
foreach(var f in funcs)
Console.WriteLine(f());
Run Code Online (Sandbox Code Playgroud)
大多数人认为它是100/110/120.实际上是120/120/120.
但是vs2015和.net 4.5.1的结果将输出 100/110/120 ,而不是 120/120/120 .
当我按如下方式测试代码时,for和之间存在一些差异foreach
var values = new List<int> {100, 110, 120};
var funcs = new List<Func<int>>();
foreach (var v in values)
funcs.Add(() =>
{
Console.WriteLine(v);
return v;
} );
foreach (var f in funcs)
Console.WriteLine(f());
//will throw exception
for (int i=0;i<values.Count;i++)
funcs.Add(() => …Run Code Online (Sandbox Code Playgroud) IEnumerable<char> query = "Not what you might expect";
string vowels = "aeiou";
for (int i = 0; i < vowels.Length; i++)
query = query.Where (c => c != vowels[i]);
foreach (char c in query) Console.Write (c);
Run Code Online (Sandbox Code Playgroud)
发生异常IndexOutOfRangeException。为什么会发生这个异常,一切看起来都很好。
提前致谢。
解决方案
for (int i = 0; i < vowels.Length; i++)
{
char vowel = vowels[i];
query = query.Where (c => c != vowel);
}
Run Code Online (Sandbox Code Playgroud)
这工作正常,这些代码有什么区别。请分享详细信息。
c# ×9
.net ×4
closures ×3
lambda ×3
linq ×3
foreach ×2
action ×1
asynchronous ×1
delegates ×1
dictionary ×1
filter ×1
for-loop ×1
threadpool ×1
vb.net ×1