C#的Dynamic、Object、Var
一、Dynamic
MSDN 杂志:动态 .NET - 了解 C# 4 中的 Dynamic 关键字 | Microsoft Learnhttps://learn.microsoft.com/zh-cn/archive/msdn-magazine/2011/february/msdn-magazine-dynamic-net-understanding-the-dynamic-keyword-in-csharp-4
1.1、Dynamic简介
编程语言可划分为【静态类型化语言】和【动态类型化语言】,其中C#和Java是被认为是静态类型化语言的例子;Python、JavaScript、Ruby是动态类型化语言的例子。
C# 最初是作为纯静态语言创建的,但 C# 4 添加了一些动态元素,用以改进与动态语言和框架之间的互操作性,即使用关键字【dynamic】来实现动态化【dynamic 关键字可充当 C# 类型系统中的静态类型声明。这样,C# 就获得了动态功能,同时仍然作为静态类型化语言而存在】。在C#中当你使用 dynamic 关键字时,类型为dynamic的对象会跳过静态类型检查,就相当于告诉编译器关闭编译时检查。
序号 | 动态类型化语言 | 静态类型化语言 |
1 | Python、JavaScript、Ruby是动态类型化语言的例子 | C#和Java是通常被认为是静态类型化语言的例子 |
2 | 一般来说,动态语言不执行编译时类型检查,仅在运行时识别对象类型 (这种方法的好处是:代码编写起来更快更容易; 这种方法的缺点是:你不会获得编译器错误,只能通过单元测试和其他方法来确保应用程序正常运行) |
C#中使用【daynamic】声明的变量,可以任意赋值,dynamic类型的实例与其他类型的实例进行转换时只用直接赋值就行。
1.2、Dynamic使用示例
值类型 - C# reference | Microsoft Learnhttps://learn.microsoft.com/zh-cn/dotnet/csharp/language-reference/builtin-types/value-types引用类型 - C# reference | Microsoft Learn
https://learn.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/reference-types
C#中的动态类型(Dynamic)_c# dynamichttps://coffeemilk.blog.csdn.net/article/details/123132592
/// <summary>
/// 测试动态类型
/// </summary>
internal class TestDynamicType
{//动态类型测试public static void DynamicTypeTest(){//直接赋值dynamic d_int = 666;Print(d_int);dynamic d_double = 66.321;Print(d_double);dynamic d_str = "Coffee Test";Print(d_str);dynamic d_bool= false;Print(d_bool);dynamic res1 = d_int + d_double;Print(res1);dynamic res2 = d_int + d_str;Print(res2);//结构体dynamic d_struct = new TestStruct();Console.WriteLine($"【{d_struct.Name}】【{d_struct.Age}】【{d_struct.IsActive}】");d_struct.Print();// d_struct.TestMethod();//运行时会报错,但是编写的时候不报错Print(d_struct);d_struct.ArgsTest(66);d_struct.ArgsTest("测试参数");//枚举dynamic d_enum = TestEnum.doc;Print(d_enum);Console.WriteLine("-------------------------");//类dynamic d_class = new TestClass(999);Console.WriteLine($"【{d_class.Name}】【{d_class.Age}】【{d_class.Dc}】");Print(d_class);d_class.Print();}//打印private static void Print(dynamic dc){Console.WriteLine($"【{dc}】数据类型是【{dc.GetType()}】");}//结构体private struct TestStruct{public string Name { get; set; } = "张三";public int Age=26;public bool IsActive = true;public TestStruct(){}public void Print(){Console.WriteLine($"姓名【{Name}】年龄【{Age}】激活【{IsActive}】");}//动态类型可作为参数public void ArgsTest(dynamic value){Console.WriteLine($"我是【{this.GetType()}/Args】方法里面被传入的动态值【{value}】我的类型是【{value.GetType()}】");}private void TestMethod(){Console.WriteLine("这是私有的测试方法");}}//枚举private enum TestEnum{doc=0,docx=2,xls=1,xlsx=3,html=4,xml=5,txt=6}//类private class TestClass{public string Name { get; set; } = "我是一个类";public double Age { get; set; } = 777;private dynamic dc;public TestClass(dynamic dc){this.dc = dc;}public dynamic Dc{get { return dc; }}public void Print(){Console.WriteLine($"【{this.GetType()}/Print()】方法打印信息 " +$"姓名【{Name}】年龄【{Age}】动态值【{dc}】");}}}//Class_end
运行结果如下:
二、Object
2.1、Object简介
Object类是所有 .NET 类的最终基类;它是类型层次结构的根;支持 .NET 类层次结构中的所有类,并为派生类提供低级别服务。任何类型可以直接赋值给object类型。
序号 | 装箱和拆箱 | 说明 |
1 | 装箱(Boxing) | 装箱是将值类型转换为 原理是:值(Value)的数据是存储在栈空间内的,当将数据转成引用型数据时是将值存储在堆空间(Heap)中,然后栈空间有一个内存存储该值的地址,这就是引用型数据的意义 |
2 | 拆箱(Unboxing) | 从 |
C#object类型的用法 Type.IsClass 属性 (System) | Microsoft Learn |
2.2、Object使用示例
C#反射详解与应用https://coffeemilk.blog.csdn.net/article/details/123005133.NET 中的反射 | Microsoft Learn
https://learn.microsoft.com/zh-cn/dotnet/fundamentals/reflection/reflection
//测试Object
private static void TestObject()
{int number = 666;TestType(number);object obj = number; //将值数据类型(int)转为object类型,称为【装箱(Boxing)】//Console.WriteLine($"【{obj}】的类型是【{obj.GetType().IsValueType}】");TestType(obj);int tmpNumber= number; //将object数据类型转为值类型(int),称为【拆箱(Unboxing)】//Console.WriteLine($"【{tmpNumber}】的类型是【{tmpNumber.GetType().IsValueType}】");TestType(tmpNumber);string str = "测试";TestType(str);object obj2 = new Car();TestType(obj2);Car car = (Car)obj2;TestType(car);Console.WriteLine($"【{car.Name}】【{car.length}】【{car.width}】【{car.height}】");
}private static void TestType(object o)
{Type T = o.GetType();bool isValueType = T.IsValueType;//值类型bool isClass = T.IsClass;//类类型(对象类型)bool isGenericType = T.IsGenericType;//泛型bool isConstructedGenericType = T.IsConstructedGenericType;//对象为构造泛型类型if (isValueType){Console.WriteLine($"【{o}】对应【{T}】是值类型");}if (isClass){Console.WriteLine($"【{o}】对应【{T}】是对象类型");}if (isGenericType){Console.WriteLine($"【{o}】对应【{T}】是泛型");}if (isConstructedGenericType){Console.WriteLine($"【{o}】对应【{T}】是构造泛型类型");}}
运行结果如下:
三、Var
3.1、Var简介
Var关键字指示编译器通过初始化语句右侧的表达式推断变量的类型。 推断类型可以是内置类型、匿名类型、用户定义类型或 .NET 类库中定义的类型。【var 在方法范围级别内可以声明,var 声明的变量可以存储任何值,但必须初始化值。因此,它属于强类型变量】。
var
关键字并不意味着“变体”,并且并不指示变量是松散类型或是后期绑定。 它只表示由编译器确定并分配最适合的类型。
在许多情况下,使用 var
是可选的,只是一种语法便利。 但是,在使用匿名类型初始化变量时,如果需要在以后访问对象的属性,则必须将变量声明为 var。
声明语句 - 局部变量和常量、var、reference 局部变量(ref 局部变量) - C# reference | Microsoft Learnhttps://learn.microsoft.com/zh-cn/dotnet/csharp/language-reference/statements/declarations#implicitly-typed-local-variables隐式类型本地变量 - C# | Microsoft Learn
https://learn.microsoft.com/zh-cn/dotnet/csharp/programming-guide/classes-and-structs/implicitly-typed-local-variables
匿名类型 - C# | Microsoft Learnhttps://learn.microsoft.com/zh-cn/dotnet/csharp/fundamentals/types/anonymous-types?source=recommendations
3.2、Var使用示例
private static void TestVar(){/*使用Var声明局部变量示例*///被编译为intvar number = 666;Print(number);//被编译为字符串var str = "Hello Coffee";Print(str);//被编译为int数组var array = new[] { 2, 1, 4, 6, 0 };Print(array);//被编译为匿名类型var obj = new {Name="Coffee",Age=27 };Print(obj);//被编译为List<int>var list=new List<int>();Print(list);}private static void Print<T>(T t){Console.WriteLine($"【{t}】的类型是【{t.GetType()}】");}
运行结果是:
四、其他资料
类型 - C# language specification | Microsoft Learnhttps://learn.microsoft.com/zh-cn/dotnet/csharp/language-reference/language-specification/types#824-the-dynamic-typeDynamicObject 类 (System.Dynamic) | Microsoft Learn
https://learn.microsoft.com/zh-cn/dotnet/api/system.dynamic.dynamicobject?view=net-9.0System 命名空间 | Microsoft Learn
https://learn.microsoft.com/zh-cn/dotnet/api/system?view=net-8.0
表达 式 - C# language specification | Microsoft Learnhttps://learn.microsoft.com/zh-cn/dotnet/csharp/language-reference/language-specification/expressions#1231-general