网站首页 > 技术文章 正文
概述:C# 中的匿名类型是无名类型,它允许您将一组只读属性捆绑到单个对象中,而无需事先显式定义类型。若要创建匿名对象,可以使用“new”关键字并在大括号中指定所需的属性。在这里,我们创建了一个具有三个属性的匿名类型:字符串类型的“Name”、字符串类型的“State”和 int 类型的“Age”。var employee = new { Name = Jack, State = Boston, Age = 43 }; Console.WriteLine($This person's name is {employee.Name}, he lives in {employee.State} an
C# 中的匿名类型是无名类型,它允许您将一组只读属性捆绑到单个对象中,而无需事先显式定义类型。
若要创建匿名对象,可以使用“new”关键字并在大括号中指定所需的属性。在这里,我们创建了一个具有三个属性的匿名类型:字符串类型的“Name”、字符串类型的“State”和 int 类型的“Age”。
var employee = new { Name = "Jack", State = "Boston", Age = 43 };
Console.WriteLine(#34;This person's name is {employee.Name}, he lives in {employee.State} and is {employee.Age} years old.");
代码的结果
匿名类型的属性是只读的,这意味着您不能在代码中修改它们:
匿名类型是只读的
让我们考虑一个简单的编码挑战,以更好地了解匿名类型的用途。
首先,我们为 'Pet' 定义一个类:
internal class Pet
{
public string Name { get; set; }
public PetTypes Type { get; set; }
public int Age { get; set; }
public Pet(string name, PetTypes type, int age)
{
Name = name;
Type = type;
Age = age;
}
}
然后,我们为“PetType”定义一个枚举:
internal enum PetTypes
{
Dog,
Cat
}
接下来,我们创建一个“宠物”集合:
var pets = new[]
{
new Pet("Hannibal", PetTypes.Dog, 12),
new Pet("Black", PetTypes.Cat, 8),
new Pet("White", PetTypes.Dog, 4),
new Pet("Red", PetTypes.Dog, 7),
new Pet("Pink", PetTypes.Dog, 7),
new Pet("Brown", PetTypes.Dog, 7)
};
每只宠物都有名称、类型和年龄。
我们想要做的是构建一个字符串集合,其中包含有关每种宠物类型的数据以及所选类型宠物的平均年龄。
我们将使用 LINQ 来执行此操作。我们需要按类型对这些宠物进行分组,然后,对于每个组,我们可以计算平均年龄:
var averageWeightsData = pets
.GroupBy(pet => pet.Type)
.Select(grouping => grouping.Average(pet => pet.Age));
foreach (var item in averageWeightsData)
{
Console.WriteLine(item);
}
这就是我想要的,但有一个问题。
每种类型的平均年龄
我们只选择了每个组的平均年龄,丢失了有关每个组名称的信息。
我想显示宠物的类型和平均年龄。
我现在该怎么办?
要同时显示宠物类型和平均年龄,创建类、结构或记录将是一个可能的解决方案。
但是,对于这种特定情况,这可能有点矫枉过正。
我将为这个非常具体的数据创建一个新类。我可能永远不会在不同的上下文中使用它。
因此,必须有更好的解决方案。
在这一点上,匿名类型再次出现。
让我们继续阅读...
答案是使用匿名类型。
匿名类型是一种在需要它的地方精确定义的类型,甚至没有给它一个名字。
它非常适合像我们这样的用例——类型很小且是临时的,我们不打算在其他任何地方使用它。 因此,让我们根据需要修改代码。
var averageWeightsData = pets
.GroupBy(pet => pet.Type)
.Select(grouping => new
{
Type = grouping.Key,
AgeAverage = grouping.Average(pet=>pet.Age)
})
.OrderBy(data => data.AgeAverage);
foreach (var item in averageWeightsData)
{
Console.WriteLine(#34;Average age for type {item.Type} is {item.AgeAverage}");
}
修改后的代码的结果如下所示。
修改代码的结果
通过在我们的代码中使用匿名类型,我们达到了预期的结果。
如何在不同的代码中使用匿名类型?
在我们的例子中,正如你所看到的,匿名类型没有名称。因此,我们不可能在其他任何地方使用它。
如果我们不知道它的名字,我们怎么能提到它呢?
实际上,编译器给它起了一个在通用中间语言中可以看到的名称,但即使我们使用反编译器来查找它,也无法使用它。
为了满足你的好奇心,我检查了编译器是如何命名这个特定类型的:
公共中间语言给出的匿名类型的名称
匿名类型的名称位于顶部。正如你所看到的,它的可读性不是很强。请注意,从公共语言运行库的角度来看,匿名类型与任何其他类型没有什么不同。
匿名类型具有几个关键特征:
- 它们仅包含只读属性,
- 其他类型的类成员(如方法或事件)均无效
- 如果没有为匿名类型的属性指定名称,编译器将使用用于设置匿名类型属性值的属性的名称。
- 匿名类型是类对象,直接派生自 System.Object。
- 它们不能被强制转换为任何其他类型的类型。
- 它们重写 Equals 和 GetHashCode 方法以支持基于值的相等。两个具有相同值的匿名对象将具有相同的哈希码,并且 Equals 方法将为它们返回 true。请注意,== 运算符没有重载,因此它将返回 false(因为它们的引用不同)。
- 它们支持带有“with”关键字的非破坏性突变。请记住:非破坏性突变不是改变原始对象,而是创建一个具有更改值的新对象。请查看下面的示例代码。
var someData = new { number = 5, text = "My name is Ozkan'" };
var changedData = someData with { number = 10 };
Console.WriteLine(#34;SomeData values: number = {someData.number}, text = {someData.text}) \n");
Console.WriteLine(#34;ChangedData values: number = {changedData.number}, text = {changedData.text})");
代码的结果是:
我们可以修改匿名类型属性的值吗?
不。匿名类型的所有属性都是只读的。
我们什么时候应该使用匿名类型,什么时候不应该使用匿名类型?
匿名类型的最佳用例是,我们想要使用的类型是简单的,并且是某些特定上下文的本地类型,并且不会在其他任何地方使用。它经常用作复杂 LINQ 查询中的临时对象。如果类型很复杂,或者我们想重用它,它不应该是匿名的。此外,匿名类型只能提供只读属性;它们不能有方法、字段、事件等,所以如果我们需要这些功能中的任何一个,匿名类型将不适合我们。
匿名类型是值类型还是引用类型?
它们是引用类型,因为它们是类,但它们使用 Equals 方法支持基于值的 Equality。换言之,Equals 方法将两个具有相同属性值的匿名对象视为相等,即使它们的引用不同。
猜你喜欢
- 2024-11-04 从原理聊JVM(一):染色标记和垃圾回收算法
- 2024-11-04 一文读懂String类的基本数据类型 strings类型
- 2024-11-04 阿里&北大:深度哈希算法最新综述
- 2024-11-04 数据结构与算法之哈希表 数据结构哈希函数
- 2024-11-04 区块链中两个最重要的数据加密安全技术,非对称加密、哈希计算
- 2024-11-04 如何识别文件的真假 识别文件真实类型最有效的方式
- 2024-11-04 大厂必备技能:数据结构之哈希表 数据结构课程设计哈希表设计
- 2024-11-04 向量数据库-相似性搜索概述 向量相似度算法
- 2024-11-04 两个对象不相等,HashCode 有可能相等吗?
- 2024-11-04 JAVA教程——equals和hashCode java中hashcode的用法
你 发表评论:
欢迎- 最近发表
-
- 在 Spring Boot 项目中使用 activiti
- 开箱即用-activiti流程引擎(active 流程引擎)
- 在springBoot项目中整合使用activiti
- activiti中的网关是干什么的?(activiti包含网关)
- SpringBoot集成工作流Activiti(完整源码和配套文档)
- Activiti工作流介绍及使用(activiti工作流会签)
- SpringBoot集成工作流Activiti(实际项目演示)
- activiti工作流引擎(activiti工作流引擎怎么用)
- 工作流Activiti初体验及在数据库中生成的表
- Activiti工作流浅析(activiti6.0工作流引擎深度解析)
- 标签列表
-
- oraclesql优化 (66)
- 类的加载机制 (75)
- feignclient (62)
- 一致性hash算法 (71)
- dockfile (66)
- 锁机制 (57)
- javaresponse (60)
- 查看hive版本 (59)
- phpworkerman (57)
- spark算子 (58)
- vue双向绑定的原理 (68)
- springbootget请求 (58)
- docker网络三种模式 (67)
- spring控制反转 (71)
- data:image/jpeg (69)
- base64 (69)
- java分页 (64)
- kibanadocker (60)
- qabstracttablemodel (62)
- java生成pdf文件 (69)
- deletelater (62)
- com.aspose.words (58)
- android.mk (62)
- qopengl (73)
- epoch_millis (61)
本文暂时没有评论,来添加一个吧(●'◡'●)