Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net “;动态”;和“;对象”;C#中的关键字?_.net_C# 4.0 - Fatal编程技术网

.net “;动态”;和“;对象”;C#中的关键字?

.net “;动态”;和“;对象”;C#中的关键字?,.net,c#-4.0,.net,C# 4.0,有人能简要解释一下C#中“动态”和“对象”关键字之间的区别吗?请查看Anders Hejlsberg的谈话,以便更好地理解动态 请在此页上查看 这些关键字指的是.NET常用类型 基本上: 对象类型是.NET Framework中对象的别名。在C#的统一类型系统中,所有类型,预定义的和用户定义的、引用类型和值类型(包括动态)都直接或间接地从对象继承。可以将任何类型的值指定给object类型的变量 谈论动态: 动态类型使发生动态类型的操作能够绕过编译时类型检查。相反,这些操作是在运行时解决的。动态类

有人能简要解释一下C#中“动态”和“对象”关键字之间的区别吗?

请查看Anders Hejlsberg的谈话,以便更好地理解动态

请在此页上查看

这些关键字指的是.NET常用类型

基本上: 对象类型是.NET Framework中对象的别名。在C#的统一类型系统中,所有类型,预定义的和用户定义的、引用类型和值类型(包括动态)都直接或间接地从对象继承。可以将任何类型的值指定给object类型的变量

谈论动态:

动态类型使发生动态类型的操作能够绕过编译时类型检查。相反,这些操作是在运行时解决的。动态类型简化了对COM API(如Office Automation API)、动态API(如IronPython库)和HTML文档对象模型(DOM)的访问

在大多数情况下,类型动态的行为与类型对象类似。但是,编译器不会解析或检查包含dynamic类型表达式的操作。编译器将有关操作的信息打包在一起,这些信息稍后用于在运行时评估操作。作为过程的一部分,dynamic类型的变量被编译成object类型的变量。因此,类型dynamic只在编译时存在,而不在运行时存在

请注意,此解释摘自MSDN页面。

  • object
    就是这样:一个简单的C#object,只有最少的方法。在.NET中,它充当所有内容的内置基类(确保所有内容至少具有
    ToString()
    Equals()
    、和
    GetHashCode()
  • dynamic
    相反,对象是完全不同的种类<代码>动态允许在其他静态类型语言中后期绑定道具和方法-引入一些功能并与动态类型语言(如Python)更好地兼容

    • 对象

      让我们首先快速查看object关键字。我不打算谈论太多,因为它从C#1.0开始就存在了。这个关键字不过是System.Object的快捷方式,它是C#类层次结构中的根类型。(然而,正如Eric Lippert在他的博客文章中指出的,并不是C#中的所有东西都来自object。)这是一种强大的机制,因为您可以为这种类型的实例分配几乎任何值

      下面是一个简短的示例,演示了使用object关键字的一些好处和问题

      object obj = 10;
      Console.WriteLine(obj.GetType());
      // Prints System.Int32 because 
      // this is the type of the value stored in this object.
      
      // A compiler error, because 
      // at compile time the type of obj is System.Object.
      // obj = obj + 10; 
      
      // You need to explicitly cast obj to a necessary type.
      obj = (int)obj + 10;
      
      // However, this does not mean that you are really safe. 
      // You can cast to a wrong type 
      // and the compiler will not detect it. 
      // Here you get an exception at run time, 
      // because obj is an integer, not a string.
      // obj = (string)obj + 10;
      
      // You also get a run-time exception 
      // if you cast to a wrong numeric type, 
      // even if there is an implicit conversion in the language.
      // obj = (double)obj + 10;
      
      object obj = 10;
      
      // Doesn't compile.
      //Print(obj);
      
      // Compiles, but there is an exception at run time.
      //Print((string)obj);
      
      // This code works because obj is now a string, 
      // but you still need a cast.
      obj = "10";
      Print((string)obj);
      
      如您所见,尽管obj存储整数,但编译器不允许您在没有强制转换的情况下执行任何数学运算。看起来,强制转换可以帮助您确保您确实拥有一个整数,但事实并非如此。您可以强制转换为完全不同的类型,编译器不会检测到它。因此,您会得到一个运行时异常

      因此,您必须执行显式强制转换,这不能保证任何东西,因为编译器不允许您在没有强制转换的情况下运行程序

      动态

      这里是C#4.0中新的动态关键字的用武之地。它告诉编译器不要对代码强制附加规则

      dynamic dyn = 10;
      Console.WriteLine(dyn.GetType());
      // Same as "object". 
      // Prints System.Int32 because 
      // this is the type of the value stored in this object.
      
      // No compiler error, because 
      // the compiler does not try to identify 
      // the type of the dynamic object at compile time.
      dyn = dyn + 10;
      
      // Also, this operation will succeed for all numeric 
      // or other types that support a “+” operation.
      dyn = 10.0;
      dyn = dyn + 10;
      
      dyn = "10";
      dyn = dyn + 10;
      
      这是object和dynamic之间的主要区别之一——使用dynamic,您告诉编译器对象的类型只能在运行时知道,并且编译器不会试图干预。因此,您可以编写更少的代码。我想强调的是,这并不比使用原始对象关键字更危险。但是,它的危险性也不亚于此,因此在操作对象(如反射)时需要使用的所有类型检查技术也必须用于动态对象

      下一个经常出现的问题是这样的:“既然动态对象可以是任何东西,而编译器不检查它是什么,这是否意味着您可以将动态对象传递给我毫无戒心的方法/系统并使其崩溃?”

      假设我们有一个简单的方法

      public static void Print(string arg)
      {
          Console.WriteLine(arg);
      }
      Now let’s look at how you can pass a dynamic object to it.
      
      dynamic dyn = 10;
      
      // You get an exception at run time here.
      Print(dyn);
      
      如您所见,尽管编译器允许您将动态对象传递给您的方法,但如果您的方法具有错误的类型,则该方法永远不会获取该对象。在实际调用该方法之前引发异常。将动态对象传递给方法的唯一方法是,它是否包含必要的值(在本例中为字符串)

      dynamic dyn = "10";
      Print(dyn);
      
      同样,这与使用object关键字获得的行为没有太大区别

      object obj = 10;
      Console.WriteLine(obj.GetType());
      // Prints System.Int32 because 
      // this is the type of the value stored in this object.
      
      // A compiler error, because 
      // at compile time the type of obj is System.Object.
      // obj = obj + 10; 
      
      // You need to explicitly cast obj to a necessary type.
      obj = (int)obj + 10;
      
      // However, this does not mean that you are really safe. 
      // You can cast to a wrong type 
      // and the compiler will not detect it. 
      // Here you get an exception at run time, 
      // because obj is an integer, not a string.
      // obj = (string)obj + 10;
      
      // You also get a run-time exception 
      // if you cast to a wrong numeric type, 
      // even if there is an implicit conversion in the language.
      // obj = (double)obj + 10;
      
      object obj = 10;
      
      // Doesn't compile.
      //Print(obj);
      
      // Compiles, but there is an exception at run time.
      //Print((string)obj);
      
      // This code works because obj is now a string, 
      // but you still need a cast.
      obj = "10";
      Print((string)obj);
      
      有人说读取(int)obj并不难,那么为什么还要麻烦使用dynamic呢?在某些情况下,您必须执行如此多的强制转换操作,以至于代码几乎无法读取。还有一些情况下,简单的强制转换是不够的,您必须调用反射方法,例如InvokeMember或GetProperties。这里的一个很好的例子是COM互操作,这就是为什么它被修改为使用新的动态特性(有关更多信息,请参阅此“操作方法”)

      此外,dynamic关键字和dynamic language runtime支持许多以前不可能或很难实现的场景,包括与动态语言的互操作。我在本博客前面已经强调了两个这样的场景:介绍ExpandoObject和使用DynamicObject创建包装器

      结论

      结论是,没有必要担心有人会使用动态特性破坏您的代码。它不比object关键字更危险(同样,也不比object关键字更危险)

      object obj = 10;
      Console.WriteLine(obj.GetType());
      // Prints System.Int32 because 
      // this is the type of the value stored in this object.
      
      // A compiler error, because 
      // at compile time the type of obj is System.Object.
      // obj = obj + 10; 
      
      // You need to explicitly cast obj to a necessary type.
      obj = (int)obj + 10;
      
      // However, this does not mean that you are really safe. 
      // You can cast to a wrong type 
      // and the compiler will not detect it. 
      // Here you get an exception at run time, 
      // because obj is an integer, not a string.
      // obj = (string)obj + 10;
      
      // You also get a run-time exception 
      // if you cast to a wrong numeric type, 
      // even if there is an implicit conversion in the language.
      // obj = (double)obj + 10;
      
      object obj = 10;
      
      // Doesn't compile.
      //Print(obj);
      
      // Compiles, but there is an exception at run time.
      //Print((string)obj);
      
      // This code works because obj is now a string, 
      // but you still need a cast.
      obj = "10";
      Print((string)obj);
      
      因此,如果您经常使用object关键字,并且必须执行大量强制转换和/或使用反射来调用对象的方法和属性,