【问题标题】:Why is C# statically typed?为什么 C# 是静态类型的?
【发布时间】:2010-10-25 22:37:36
【问题描述】:

我是一名 PHP 网络程序员,正在努力学习 C#。

我想知道为什么 C# 要求我在创建变量时指定数据类型。

Class classInstance = new Class();

为什么我们需要在类实例之前知道数据类型?

【问题讨论】:

  • 好吧,你也可以输入var classInstance = new Class();FYI
  • @Jeff Atwood,是的,但是当您要声明 A 类型的变量并将其实例化为其后代之一时,这不起作用。最好保持一致,到处都有“var”,并在其他地方明确指定类型名称。

标签: c# static-typing


【解决方案1】:

其中一个主要原因是您可以指定不同的类型,只要赋值左侧的类型是左侧类型的父类型(或在该类型上实现的接口)。

例如给定以下类型:

class Foo { }
class Bar : Foo { }
interface IBaz { }
class Baz : IBaz { }

C# 允许您这样做:

Foo f = new Bar();
IBaz b = new Baz();

是的,在大多数情况下,编译器可以从赋值中推断出变量的类型(例如使用 var 关键字),但它不适用于原因我已经在上面展示了。

编辑: 作为一个程序点 - 虽然 C# 强类型的重要区别(就本讨论而言)是它实际上也是静态类型语言。换句话说,C# 编译器在编译时进行静态类型检查。

【讨论】:

  • +1,因为这是为数不多的回答“为什么会这样工作”而不是“因为这样”的答案之一。
  • 如果类型之间存在隐式转换,则左侧的类型不必是父类型或实现的接口。示例:XNamespace ns = "http://url.com";
【解决方案2】:

静态类型意味着编译器可以在编译时而不是在运行时执行某种检查。在静态类型中,每个变量都是特定类型或强类型。 C# 绝对是强类型的。

【讨论】:

    【解决方案3】:

    正如其他人所说,C# 是静态/强类型的。但我认为您的问题更多是“为什么您希望 C# 像这样静态/强类型?这与动态语言相比有什么优势?”

    考虑到这一点,有很多充分的理由:

    • 稳定性现在,编译器会在代码接近生产之前自动捕获某些类型的错误。
    • 可读性/可维护性您现在向阅读它的未来开发人员提供有关代码应该如何工作的更多信息。您添加特定变量旨在保存某种值的信息,这有助于程序员推断该变量的目的是什么。

      这可能就是为什么,例如,微软的风格指南建议 VB6 程序员在变量名中加上类型前缀,而 VB.Net 程序员却不这样做。

    • 性能这是最弱的原因,但后期绑定/鸭子打字可能会更慢。最后,变量指的是以某种特定方式构造的内存。如果没有强类型,程序将不得不在运行时在后台进行额外的类型验证或转换,因为您使用的内存在物理上以一种方式构造,就好像它在逻辑上以另一种方式构造一样。

      我不愿提及这一点,因为最终您通常还必须使用强类型语言进行这些转换。只是强类型语言将转换的确切时间和范围留给了程序员,除非需要做,否则不会做额外的工作。它还允许程序员强制使用更有利的数据类型。但这些确实是程序员的属性,而不是平台的属性。

      这本身就是一个忽略这一点的弱理由,除了一个好的动态语言通常会比程序员做出更好的选择。这意味着动态语言可以帮助许多程序员编写更快的程序。不过,对于优秀的程序员来说,强类型语言有潜力更快。

    • 更好的开发工具 如果您的 IDE 知道变量的预期类型,它可以为您提供有关该变量可以做什么类型的额外帮助。如果 IDE 必须为您推断类型,这对 IDE 来说要困难得多。如果您从 IDE 获得有关 API 细节的更多帮助,那么作为开发人员,您将能够了解更大、更丰富的 API,并更快地实现目标。

    或者您可能只是想知道为什么必须在同一行中为同一个变量指定两次类名?答案有两个:

    1. 通常你不知道。在 C# 3.0 及更高版本中,您可以在许多情况下使用 var 关键字代替类型名称。以这种方式创建的变量仍然是静态类型的,但类型现在由编译器为您推断
    2. 由于继承和接口,有时左侧的类型与右侧的类型不匹配。

    【讨论】:

    • 静态类型和强类型不是一回事
    • 好点。对于似乎理解这个主题的人的问题:是否有可能拥有静态/强类型的解释语言?我还没有见过,但根据你所说的,我不明白为什么我们不能拥有一个。我知道我们不会在编译时捕获类型错误,因为没有,但似乎我们会看到其他一些好处(智能感知)。在 C# 中工作多年后,由于动态类型,尝试用 Javascript 编写代码让我发疯。
    • 强类型解释语言有点奇怪,因为使用解释器的部分理念是你可以让它只解释 sn-ps。当您开始不得不将类定义与 sn-ps 一起移植时,解释器开始失去与编译语言相比的吸引力。但没有什么能阻止你。
    • 其实Java最初是解释型的,是一种强类型语言。
    • 许多 ML 家族语言(具有非常好的灵活的静态类型系统和几乎完美的通用类型推断(如 c# 中的 var 但几乎总是有效)都有解释器和编译器。Haskell 有拥抱,标准 ml 有 HaMLet 等。
    【解决方案4】:

    为什么 C# 要求我在创建变量时指定数据类型。

    为什么我们需要在类实例之前知道数据类型?

    我认为大多数答案没有提到的一件事是,C#最初是指和设计为“托管”、“安全”语言等,其中许多目标是通过静态/编译时可验证性得出。明确地知道变量数据类型使这个问题更容易解决。这意味着一个人可以对可能的错误/不良行为进行多次自动评估(C# 编译器,而不是 JIT),而无需允许执行。

    作为副作用的可验证性还为您提供更好的可读性、开发工具、稳定性等,因为如果自动化算法可以更好地理解代码在实际运行时会做什么,那么您也可以:)

    【讨论】:

      【解决方案5】:

      静态类型还允许编译器进行更好的优化,并跳过某些步骤。以重载为例,你有多个方法或运算符具有相同的名称,只是它们的参数不同。对于动态语言,运行时需要对每个版本进行评分以确定哪个是最佳匹配。使用像这样的静态语言,最终代码只是直接指向适当的重载。

      静态类型还有助于代码维护和重构。我最喜欢的例子是许多高端 IDE 的重命名功能。由于采用了静态类型,IDE 可以确定地找到代码中标识符的每一次出现,并保留不相关的同名标识符。

      我没有注意到它是否被提及,但 C# 4.0 通过 dynamic 关键字引入了动态检查。虽然我敢肯定你会想在不必要的时候避免它。

      【讨论】:

        【解决方案6】:

        为什么我们需要知道数据类型 类实例之前?

        你没有! 从右到左阅读。创建变量,然后将其存储在类型安全的变量中,以便知道该变量的类型以供以后使用。

        考虑以下 sn-p,如果直到运行时才收到错误,调试将是一场噩梦。

         void FunctionCalledVeryUnfrequently()
         {
           ClassA a = new ClassA();
           ClassB b = new ClassB();
           ClassA a2 = new ClassB(); //COMPILER ERROR(thank god)
        
           //100 lines of code
        
           DoStuffWithA(a);
           DoStuffWithA(b);      //COMPILER ERROR(thank god)
           DoStuffWithA(a2);
         }
        

        当您考虑可以将 new Class() 替换为数字或字符串时,语法会更有意义。下面的例子可能有点冗长,但可能有助于理解为什么它是这样设计的。

           string s = "abc";
           string s2 = new string(new char[]{'a', 'b', 'c'});
           //Does exactly the same thing
        
           DoStuffWithAString("abc");
           DoStuffWithAString(new string(new char[]{'a', 'b', 'c'}));
           //Does exactly the same thing
        

        【讨论】:

          【解决方案7】:

          最终因为 Anders Hejlsberg 这么说......

          【讨论】:

          • 我们都应该心存感激。
          【解决方案8】:

          还有一点没有提到,C# 是一种符合 CLS(通用语言规范)的语言。这是 .NET 语言必须遵守的一组规则,才能与其他 .NET 语言互操作。

          所以说真的 C# 只是遵守这些规则。引用this MSDN article:

          CLS 有助于增强和确保 通过定义语言互操作性 开发人员可以使用的一组功能 依靠在广泛的范围内可用 多种语言。 CLS 也 建立 CLS 的要求 遵守;这些可以帮助您确定 您的托管代码是否符合 CLS 以及给定的程度 工具支持开发 使用 CLS 功能的托管代码。

          如果您的组件仅使用 CLS 它公开的 API 中的功能 其他代码(包括派生的 类),该组件是有保证的 可以从任何程序中访问 支持 CLS 的语言。 遵守 CLS 的组件 规则并仅使用功能 据说包含在 CLS 中的是 符合 CLS 的组件

          CLS 的一部分是 CTS Common Type System

          如果这些首字母缩略词对您来说还不够,那么 .NET 中还有更多的缩略词,例如 CLI、ILasm/MSIL、CLR、BCL、FCL,

          【讨论】:

          • CLS 不需要静态类型。
          【解决方案9】:

          这就是语言的设计方式。 C# 是一种 C 风格的语言,遵循左侧类型的模式。

          在 C# 3.0 及更高版本中,在许多情况下,您可以通过本地类型推断来解决这个问题。

          var variable = new SomeClass();
          

          但同时你也可以争辩说你仍然在 LHS 上声明一个类型。只是你想让编译器为你挑选它。

          编辑

          请在用户原始问题的上下文中阅读此内容

          为什么我们在变量名之前需要[类名]?

          我想评论这个帖子中的其他几个答案。很多人给出“C# 是静态类型”作为答案。虽然该陈述是正确的(C# 是静态类型的),但它几乎与问题完全无关。静态类型不需要类型名称位于变量名称的左侧。当然它可以提供帮助,但这是语言设计者的选择,而不是静态类型语言的必要特性。

          这些很容易通过考虑其他静态类型语言(例如 F#)来证明。 F# 中的类型出现在变量名的右侧,并且通常可以完全省略。还有几个反例。例如,PowerShell 是非常动态的,它会将其所有类型(如果包含)放在左侧。

          【讨论】:

            【解决方案10】:

            正如其他人所指出的,C# 是一种强静态类型的语言。

            通过预先说明您打算创建的类型是什么,当您尝试分配非法值时,您会收到编译时警告。通过预先说明您在方法中接受的参数类型,当您不小心将废话传递给不期望它的方法时,您会收到相同的编译时警告。它代表您消除了一些偏执狂的开销。

            最后,相当不错的是,C#(和许多其他语言)没有 PHP 那样可笑的“将任何东西转换为任何东西,即使它没有意义”的心态,坦率地说,这会让你感到困惑比它有用的次数更多。

            【讨论】:

            • (强类型或弱类型)和(静态类型检查或鸭子类型)。不要混淆 :) 例如 Ruby 是强类型并且使用鸭子类型。
            【解决方案11】:

            C# 是一种statically-typedstrongly-typed 语言,类似于 C 或 C++。在这些语言中,所有变量都必须声明为特定类型。

            【讨论】:

            • 我们称它为静态类型 ;-)
            • 好点,那些语言是强类型的,带有动态类型检查(IE,运行时)。而 C# 需要类型,因此它可以在编译时执行类型检查(IE,静态检查)。
            • 编辑以涵盖静态类型
            • C# 静态类型和强类型的事实并不能回答为什么类型必须在 LHS 上的问题。这些都是不相关的问题。以 F# 或 OCaml 为例。两者都是强类型和静态类型,但无需显式键入变量就可以编写程序,如果声明它就在右边。
            • JavaScript 不是强类型,而是弱类型。 "1" + 0 将导致 "10"(串联)。
            【解决方案12】:

            在 C# 3.0 中,您可以使用 'var' 关键字 - 这使用静态类型推断来计算编译时变量的类型

            var foo = new ClassName();
            

            从那时起,变量 'foo' 的类型将是 'ClassName'。

            【讨论】:

              【解决方案13】:

              当我们定义变量来保存数据时,我们必须指定这些变量将保存的数据类型。然后编译器检查我们对数据所做的事情是否有意义,即遵循规则。例如,我们不能将文本存储在数字中 - 编译器不允许这样做。

              int a = "fred"; // Not allowed. Cannot implicitly convert 'string' to 'int' 
              

              变量 a 是 int 类型,并且将值“fred”分配给它是一个文本字符串违反了规则 - 编译器无法对该字符串进行任何类型的转换。

              【讨论】:

                【解决方案14】:

                前面需要[class name],因为很多情况下第一个[class name]和第二个不同,比如:

                 IMyCoolInterface obj = new MyInterfaceImplementer();
                 MyBaseType obj2 = new MySubTypeOfBaseType();
                

                等等。如果您不想明确指定类型,也可以使用“var”一词。

                【讨论】:

                • 如果你要 -1 的答案,你能至少给我留个便条,说明我为什么/哪里错了吗?
                • +1 因为从 C# 3 的角度来看,您的答案是完全有效的;即类型是可选的,您必须声明它的一个原因是因为您不希望 var 做出选择。
                • 虽然这本身是正确的,但它并不能回答手头的问题,这就是 C# 被静态类型化的原因(如好处或推理)。
                • 问题不是“为什么 C# 是静态类型的”。问题是:“为什么我必须指定 [classname] 两次?”这个答案是:“因为它并不总是多余的。”其他人回答“它是静态类型的”这一事实并没有提出“为什么 C# 是静态类型的”这个问题。
                • 当然,当我输入此内容时,我注意到问题已被编辑。没关系。
                【解决方案15】:

                这就是强类型语言和弱类型语言之间的区别。 C#(以及 C、C++、Java,最强大的语言)是强类型的,因此您必须声明变量类型。

                【讨论】:

                • 不,这是静态类型语言和动态类型语言之间的区别。有些语言是强类型的(因为任何对象都是可确定的类型,并遵守适当的规则)并且不需要声明变量类型。
                【解决方案16】:

                c# 是一种强类型语言,如 c++ 或 java。因此它需要知道变量的类型。您可以通过 var 关键字在 c# 3.0 中稍加修改。这让编译器可以推断类型。

                【讨论】:

                  【解决方案17】:

                  因为 C# 是一种强类型语言

                  【讨论】:

                  • 哈哈......你赢得了答案的洪流。保持简短的方法。
                  • 静态输入是主要原因。许多动态语言也是强类型的,但它们不需要类型声明。
                  • 强类型和变量名的位置是完全不相关的问题
                  • Common Lisp 也是强类型的,因为您可以非常精确地找到任何对象的类型。它不是静态类型的,因为该类型可以更改。
                  猜你喜欢
                  • 2014-09-27
                  • 2023-03-28
                  • 1970-01-01
                  • 1970-01-01
                  • 2010-10-16
                  • 2014-12-27
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多