能否在LINQ的select子句中声明函数?(MS Exam 70-483备考疑问)
能否在LINQ查询的匿名类型中添加自定义ToString逻辑?
嘿,这个问题问得很到位!备考MS Exam 70-483的时候抠这种细节,绝对能帮你更透彻理解C#匿名类型和LINQ的特性~答案是完全可以实现,不过你原代码里的写法有语法问题,咱们来一步步修正并实现需求。
首先,修正匿名类型中自定义ToString的写法
匿名类型里不能直接用ToString = Func<string>(() => { ... })这种语法,得显式创建Func<string>的实例赋值给属性。这里的ToString会成为匿名类型的一个委托属性,而不是重写Object的ToString方法。
完整可运行代码示例
class Person { public string Name { get; set; } public int CityId { get; set; } } class City { public string Name { get; set; } public int Id { get; set; } } // 模拟填充数据源 var people = new List<Person> { new Person { Name = "Alice", CityId = 1 }, new Person { Name = "Bob", CityId = 2 }, new Person { Name = "Charlie", CityId = 1 } }; var cities = new List<City> { new City { Name = "New York", Id = 1 }, new City { Name = "London", Id = 2 } }; // 正确实现自定义ToString逻辑的LINQ查询 var personsByCity = from p in people join c in cities on p.CityId equals c.Id select new { PersonName = p.Name, CityName = c.Name, // 创建Func<string>委托,返回自定义格式化字符串 ToString = new Func<string>(() => $"{PersonName} resides in {CityName}") }; // 调用自定义ToString逻辑 foreach (var entry in personsByCity) { Console.WriteLine(entry.ToString()); // 输出类似:Alice resides in New York }
注意点
- 这里的
ToString是匿名类型的属性,类型是Func<string>,所以必须加括号调用entry.ToString(),直接写entry.ToString会输出委托的类型信息(比如System.Func1[System.String]`)。 - 匿名类型无法重写Object的默认ToString方法,所以如果想让
Console.WriteLine(entry)自动调用你的自定义逻辑,匿名类型做不到——这时候推荐用具名类型替代。
更优雅的方案:使用具名类型(Record或自定义类)
如果这个需要自定义ToString的类型会被多次使用,或者你希望它的行为更符合常规类型(比如自动调用ToString),用C#的record类型(C# 9及以上)或者自定义类会更合适:
用Record类型实现(推荐)
// 定义一个Record,重写ToString方法 public record PersonCity(string PersonName, string CityName) { public override string ToString() => $"{PersonName} lives in {CityName}"; } // LINQ查询直接返回这个Record var personsByCity = from p in people join c in cities on p.CityId equals c.Id select new PersonCity(p.Name, c.Name); // 直接输出即可自动调用重写的ToString foreach (var entry in personsByCity) { Console.WriteLine(entry); // 自动输出:Alice lives in New York }
用自定义类实现(兼容旧版C#)
public class PersonCity { public string PersonName { get; set; } public string CityName { get; set; } public PersonCity(string personName, string cityName) { PersonName = personName; CityName = cityName; } public override string ToString() => $"{PersonName} lives in {CityName}"; } // LINQ查询用法和Record版本一致
两种方案各有优势:匿名类型适合临时快速构建数据结构,具名类型适合需要复用、可读性要求高的场景。
内容的提问来源于stack exchange,提问作者kmontgom
相关产品推荐
相关产品推荐

