我有一个对象列表,我想循环遍历该列表并启动一个新线程,传入当前对象.
我写了一个我认为应该做的事情的例子,但它不起作用.具体来说,似乎线程在每次迭代时都会被覆盖.这对我来说真的没有意义,因为我每次都在创建一个新的Thread对象.
这是我写的测试代码
class Program
{
static void Main(string[] args)
{
TestClass t = new TestClass();
t.ThreadingMethod();
}
}
class TestClass
{
public void ThreadingMethod()
{
var myList = new List<MyClass> { new MyClass("test1"), new MyClass("test2") };
foreach(MyClass myObj in myList)
{
Thread myThread = new Thread(() => this.MyMethod(myObj));
myThread.Start();
}
}
public void MyMethod(MyClass myObj) { Console.WriteLine(myObj.prop1); }
}
class MyClass
{
public string prop1 { get; set; }
public MyClass(string input) { this.prop1 = input; }
}
Run Code Online (Sandbox Code Playgroud)
我机器上的输出是 …
为什么我的参数x表现得如此不规律?
x因为它是在"子"范围内定义的.例1:
List<int> list = new List<int> { 1, 2, 3, 4, 5 };
var result = list.Where(x => x < 3);
Console.Write(result.ElementAt(x));
Run Code Online (Sandbox Code Playgroud)
创建此编译时错误:
当前上下文中不存在名称"x"
我期待的.
例2:
List<int> list = new List<int> { 1, 2, 3, 4, 5 };
var result = list.Where(x => x < 3);
int x = 1;
Console.Write(result.ElementAt(x));
Run Code Online (Sandbox Code Playgroud)
产生这个编译时错误:
名为'x'的局部变量不能在此范围内声明,因为它会给'x'赋予不同的含义,'x'已在'子'范围内用于表示其他内容
我理解在这个问题中回答的范围,C#在foreach中重用变量是否有原因?.然而,这是我以前从未见过的.另外,它回答了这个问题,C#中lambda变量的范围是什么?,不完整或错误.
例3:
List<int> list = new …Run Code Online (Sandbox Code Playgroud) 我已经解决了这个问题,但我正在试图找出它的工作原理.基本上,我使用foreach循环遍历结构列表.如果我在调用struct的方法之前包含引用当前结构的LINQ语句,则该方法无法修改结构的成员.无论是否甚至调用LINQ语句,都会发生这种情况.我能够通过将我正在寻找的值分配给变量并在LINQ中使用它来解决这个问题,但我想知道是什么导致了这一点.这是我创建的一个例子.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WeirdnessExample
{
public struct RawData
{
private int id;
public int ID
{
get{ return id;}
set { id = value; }
}
public void AssignID(int newID)
{
id = newID;
}
}
public class ProcessedData
{
public int ID { get; set; }
}
class Program
{
static void Main(string[] args)
{
List<ProcessedData> processedRecords = new List<ProcessedData>();
processedRecords.Add(new ProcessedData()
{
ID = 1
});
List<RawData> rawRecords = new List<RawData>(); …Run Code Online (Sandbox Code Playgroud) 我有一个嵌套列表,
List<List<String>> intable;
Run Code Online (Sandbox Code Playgroud)
在哪里我想对所有列进行排序.问题是列数取决于用户输入.
像这样排序列表工作正常(假设此示例为4列)
var tmp = intable.OrderBy(x => x[0]);
tmp = tmp.ThenBy(x => x[1]);
tmp = tmp.ThenBy(x => x[2]);
tmp = tmp.ThenBy(x => x[3]);
intable = tmp.ToList();
Run Code Online (Sandbox Code Playgroud)
但是,当我把它放在循环中时,像这样:
var tmp = intable.OrderBy(x => x[0]);
for (int i = 1; i <= 3; i++)
{
tmp = tmp.ThenBy(x => x[i]);
}
intable = tmp.ToList();
Run Code Online (Sandbox Code Playgroud)
它不再正常工作,只排序第四列.
现在,我对continue语句有一个重大问题.FetchUnseenMessages可能会也可能不会返回错误,具体取决于它是否能够连接到指定的电子邮件帐户.如果FetchUnseenMessages失败,我希望continue语句返回到foreach语句中的下一个项目(尝试下一个电子邮件帐户).我得到了一些意想不到的结果.我不相信continue语句会转到foreach语句中的下一个项目,但会回到try语句的开头并再次尝试它.我整天都被困在这里,而且我很困难.请帮忙.谢谢,克里斯.
foreach (string l in lUserName)
{
try
{
newMessages = FetchUnseenMessages(sUsername);
}
catch
{
continue;
}
//Other code
}
Run Code Online (Sandbox Code Playgroud) 我有一个简单的应用程序与以下代码:
FileInfo[] files = (new DirectoryInfo(initialDirectory)).GetFiles();
List<Thread> threads = new List<Thread>(files.Length);
foreach (FileInfo f in files)
{
Thread t = new Thread(delegate()
{
Console.WriteLine(f.FullName);
});
threads.Add(t);
}
foreach (Thread t in threads)
t.Start();
Run Code Online (Sandbox Code Playgroud)
让我们说在'I = initialDirectory'目录中我有3个文件.然后,该应用程序应创建3个线程,每个线程打印一个文件名; 但是,每个线程将打印出'files'数组中最后一个文件的名称.
为什么是这样?为什么当前文件'f'变量无法正确设置匿名方法?
在C#5中,foreach语句的闭包语义(当迭代变量被匿名函数"捕获"或"关闭"时)发生了着名的变化(链接到该主题的线程).
问题:是否打算更改指针类型数组?
为什么我想问的原因是,一个的"扩张" foreach的语句已被改写,由于技术原因(我们不能使用Current的财产System.Collections.IEnumerator,因为该物业已声明的类型object是不兼容的指针类型)相比foreach于其他藏品.C#语言规范中的相关部分,"指针数组",在5.0版本中说:
foreach (V v in x) EMBEDDED-STATEMENT
Run Code Online (Sandbox Code Playgroud)
扩展到:
{
T[,,…,] a = x;
V v;
for (int i0 = a.GetLowerBound(0); i0 <= a.GetUpperBound(0); i0++)
for (int i1 = a.GetLowerBound(1); i1 <= a.GetUpperBound(1); i1++)
…
for (int in = a.GetLowerBound(N); iN <= a.GetUpperBound(n); iN++) {
v = (V)a.GetValue(i0,i1,…,iN);
EMBEDDED-STATEMENT
}
}
Run Code Online (Sandbox Code Playgroud)
我们注意到声明V v;在所有for循环之外.因此看起来闭包语义仍然是"旧的"C#4风格,"循环变量被重用,循环变量相对于循环变为"外部".
为了说明我在说什么,请考虑这个完整的C#5计划:
using …Run Code Online (Sandbox Code Playgroud) 我有一个foreach需要转换为for或while循环的循环.我的循环看起来像这样:
foreach (Item item in Items)
{
// some stuff
}
Run Code Online (Sandbox Code Playgroud)
什么是等价物for或while循环?
我想我需要用来GetEnumerator获得IEnumerator<Item>,但我不知道如何正确使用它.Items不是列表,否则我会使用索引.
在实现表值参数时,生成IEnumerable<SqlDataRecord>参数使用的最常见方法之一是这样的代码(例如,https://stackoverflow.com/a/10779567/18192):
public static IEnumerable<SqlDataRecord> Rows(List<int> simpletable)
{
var smd = new []{ new SqlMetaData("id", SqlDbType.Int)};
var sqlRow = new SqlDataRecord(smd);
foreach (int i in simpletable)
{
sqlRow.SetInt32(0, i);
yield return sqlRow;
}
}
//...
var param = sqlCmd.Parameters.AddWithValue("@retailerIDs", Rows(mydata));
param.SqlDbType = SqlDbType.Structured;
param.TypeName = "myTypeName";
Run Code Online (Sandbox Code Playgroud)
这段代码似乎确实有效.虽然重用SqlMetaData并没有引发太多的警钟,但声明SqlDataRecord外面的foreach循环让我感到非常怀疑:
修改可变对象,然后重复生成.
作为一个关于这个问题的一个例子,var x = Rows(new[] { 100, 200}.ToList()).ToList().Dump()在LinqPad中调用吐出来200,200.这种方法似乎依赖于实现细节(行是单独处理的),但我没有看到任何承诺这样做的文档.
是否有一些减轻因素使这种方法安全?
我用C#3.5和4.0执行了以下代码.结果完全不同.
static void Main()
{
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
List<IEnumerable<int>> results = new List<IEnumerable<int>>();
foreach (var num in numbers)
{
results.Add(numbers.Where(item => item > num));
}
foreach (var r in results)
{
Console.WriteLine("{0}", r.Count());
}
}
Run Code Online (Sandbox Code Playgroud)
使用Microsoft(R)Visual C#2008编译器版本3.5.30729.5420,输出为0 0 0 0 0 0 0 0 0 0.
但是使用Microsoft(R)Visual C#Compiler版本4.0.30319.17929输出9 8 7 6 5 4 3 2 1 0.
我有一个微弱的想法,这是因为延迟执行或延迟评估,但还没有清楚地理解它是如何负责不同的输出在这里.
更正:对不起,它是.NET 3.5和4.5,还添加了编译器版本 请解释.