动态与对象类型
Posted
技术标签:
【中文标题】动态与对象类型【英文标题】:dynamic vs object type 【发布时间】:2011-03-27 10:46:35 【问题描述】:我交替使用动态和对象类型。这两种类型有什么区别吗?使用其中一种对性能有影响吗?其中哪一个更灵活?
【问题讨论】:
C# 动态添加了 C# 中缺少的功能。 VB.net 的对象(选项严格关闭)与动态相同。 ***.com/questions/2889974/… 【参考方案1】:随着 C# 语言的进步,我们已经看到了 dynamic 和 object 类型。以下是两种类型,我通过比较这 7 点了解到:
对象
-
Microsoft 在 C# 1.0 中引入了 Object 类型。
它可以存储任何值,因为“对象”是 .NET 框架中所有类型的基类。
编译器几乎没有关于类型的信息。
我们可以将对象类型作为方法参数传递,方法也可以返回对象类型。
我们需要将对象变量转换为原始类型以使用它并执行所需的操作。
如果存储的值未转换或强制转换为基础数据类型,对象可能会在运行时导致问题。
当我们没有关于数据类型的更多信息时很有用。
动态
-
动态是在 C# 4.0 中引入的
它可以存储任何类型的变量,类似于 Visual Basic 处理变量的方式。
它不是类型安全的,即编译器没有关于变量类型的任何信息。
方法既可以接受动态类型作为参数,也可以返回它。
强制类型转换不是必须的,但需要了解存储类型相关的属性和方法。
如果访问了错误的属性或方法,Dynamic 类型可能会导致问题,因为与编译时相比,有关存储值的所有信息都在运行时解析。
当我们需要使用反射或动态语言或由于编写的代码较少而需要使用 COM 对象进行编码时很有用。
希望这会对某人有所帮助。
【讨论】:
我的理解是 var 根本不是一种类型——它只是根据初始化值隐式地决定类型。例如:var x = 2; x 不是 var 类型,它是 int 类型。 那么动态不是让 C# 类型不安全吗?【参考方案2】:有一篇文章解释了不同的类型,包括对象和动态类型。文章还通过一个很好的例子解释了两者之间的区别。
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/reference-types
我将简要介绍文章中解释的差异:
对象类型是 .NET 中 System.Object 的别名。在 C# 的统一类型系统中,所有类型,预定义的和用户定义的,引用类型和值类型,都直接或间接地继承自 System.Object。您可以将任何类型的值分配给对象类型的变量。
动态类型表示使用变量和对其成员的引用绕过编译时类型检查。相反,这些操作是在运行时解决的。动态类型简化了对 COM API(例如 Office 自动化 API)、动态 API(例如 IronPython 库)以及 html 文档对象模型 (DOM) 的访问。
在大多数情况下,动态类型的行为类似于类型对象。特别是,任何非空表达式都可以转换为动态类型。动态类型与对象的不同之处在于,包含动态类型表达式的操作不会被编译器解析或类型检查。编译器将有关操作的信息打包在一起,这些信息稍后用于在运行时评估操作。作为该过程的一部分,动态类型的变量被编译为对象类型的变量。因此,动态类型只存在于编译时,而不是运行时。
总结:
这本质上意味着 object 是一种类型,所有其他类型都继承自它。 动态并不是真正的类型,它更像是指针或其他类型的表示,将在运行时解析。
【讨论】:
【参考方案3】:用简单的语言: 假设我们有以下方法:
public static void ConsoleWrite(string inputArg)
Console.WriteLine(inputArg);
对象:以下代码有编译错误,除非将对象转换为字符串:
public static void Main(string[] args)
object obj = "String Sample";
ConsoleWrite(obj);// compile error
ConsoleWrite((string)obj); // correct
Console.ReadKey();
动态:以下代码编译成功,但如果它包含除string
之外的值,则会引发运行时错误
public static void Main(string[] args)
dynamic dyn = "String Sample";
ConsoleWrite(dyn); // correct
dyn = 1;
ConsoleWrite(dyn);// Runtime Error
Console.ReadKey();
【讨论】:
【参考方案4】:它们非常不同。
如果您使用dynamic
,则您选择了动态类型,因此大部分情况下都选择退出编译时检查。是的,它的性能不如使用静态类型你可以使用静态类型。
但是,无论如何,object
类型并不能做太多事情 - 它几乎没有任何成员。你发现自己在哪里使用它?当你想编写可以处理多种类型的通用代码时,你通常应该考虑泛型而不是object
。
【讨论】:
如果 Luke 只是调用了System.Object
中可用的少数方法,它们也会被动态调用吗?
@Steven:是的,它确实如此——即使GetType
是非虚拟的! (例如,您可以设置一个代表来响应 GetType
对 ExpandoObject
的调用。可怕的东西。)
这就是我害怕的。看起来我们需要通过向上转换到object
来“装箱”dynamic
,如果我们甚至想知道它的类型的真相。 :-)
@Steven:这不会执行任何实际拳击。它可能涉及转换的动态尝试,但动态变量的基础字段(或局部变量)类型已经是object
。
是的,这就是为什么我把“盒子”放在引号里。我的意思是将dynamic
实例分配给object
别名,以避免在调用GetType
时进行运行时检查。但是既然你提到了它,就没有理由认为演员阵容会静态执行。也许它可以尝试定义一个隐式转换!以上是关于动态与对象类型的主要内容,如果未能解决你的问题,请参考以下文章