数据文件: (Data.txt) 行代表 width height
5
6 9
7 2
4 4
C#代码:
var list = new List<dynamic>();
using (var sr = new StreamReader("Data.txt", Encoding.UTF8))
{
list = sr.ReadToEnd().Split('\n').Select(r =>
{
var split = r.Split(' ');
var len = split.Length;
return new {
w = len > 0 ? int.Parse(split[0].Trim()) : 0,
h = len > 1 ? int.Parse(split[1].Trim()) : 0
} as dynamic;
}).ToList();
}
int Area = list.Sum(r => r.h * r.w);
该示例按原样运行。我不得不做一些不受欢迎的事情才能让它发挥作用。
首先,我必须声明列表以避免使用范围 - 因为我没有类型化的维度对象,所以我将类型设为动态 (var list = new List<dynamic>()
)。
不受欢迎的部分是将匿名对象转换为动态对象 ( as dynamic
)。否则我得到
Cannot implicitly convert type
System.Collections.Generic.List<AnonymousType#1>
toSystem.Collections.Generic.List<dynamic>
为什么会出现此错误?我知道动态可以包含匿名类型,所以这是 ToList()
的问题吗?扩展和动态?
我需要能够访问 using 语句之外的匿名列表项,如计算面积的最后一行。
解决方案: 我接受了 dtb 的回答。它避免了一起使用 using 语句和动态。谢谢大家的意见!
var list =
(from line in File.ReadLines("Data.txt")
let parts = line.Split(' ')
let width = int.Parse(parts[0])
let height = parts.Length > 1 ? int.Parse(parts[1]) : 0
select new { width, height }).ToList();
最佳答案
您可以使用 File.ReadLines避免 StreamReader。
IEnumerable<dynamic> query =
from line in File.ReadLines("Data.txt")
let parts = line.Split(' ')
let width = int.Parse(parts[0])
let height = parts.Length > 1 ? int.Parse(parts[1]) : 0
select new { width, height } as dynamic;
List<dynamic> list = query.ToList();
int area = list.Sum(t => t.width * t.height);
但是,正如其他人指出的那样,在这里使用动态并不合适。如果您仅在方法中使用查询,匿名实例就足够了。如果要在方法外部使用查询结果,请创建一个小结构或类或使用 Tuple
关于C# 4.0 隐式类型动态对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4349712/