32

我是一名尝试学习 C# 的 PHP Web 程序员。

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

Class classInstance = new Class();

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

4

17 回答 17

110

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

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

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

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

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

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

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

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

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

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

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

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

var variable = new SomeClass();

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

编辑

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

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

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

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

于 2009-05-13T17:07:43.480 回答
21

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

例如给定以下类型:

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

C# 允许您这样做:

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

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

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

于 2009-05-13T17:10:34.020 回答
17

C# 是一种静态类型强类型语言,如 C 或 C++。在这些语言中,所有变量都必须声明为特定类型。

于 2009-05-13T17:07:05.057 回答
9

最终因为安德斯·海尔斯伯格是这么说的……

于 2009-05-13T19:41:33.337 回答
5

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

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

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

于 2009-05-13T17:07:43.447 回答
3

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

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

考虑以下代码段,如果您在运行时才收到错误,那么调试将是一场噩梦。

 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
于 2009-07-12T12:25:14.670 回答
2

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

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

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

于 2009-05-13T17:11:51.070 回答
1

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

于 2009-05-13T17:07:40.437 回答
1

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

于 2009-05-13T17:07:42.387 回答
1

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

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

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

于 2009-05-13T17:08:16.083 回答
1

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

var foo = new ClassName();

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

于 2009-05-13T17:10:03.490 回答
1

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

所以真的 C# 只是遵守这些规则。引用这篇 MSDN 文章

CLS 通过定义一组开发人员可以依赖以提供多种语言的功能来帮助增强和确保语言互操作性。CLS 还制定了 CLS 合规性要求;这些可帮助您确定您的托管代码是否符合 CLS,以及给定工具在多大程度上支持使用 CLS 功能的托管代码的开发。

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

CLS 的一部分是 CTS通用类型系统

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

于 2009-05-13T19:07:47.947 回答
0

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

于 2009-05-13T17:07:01.217 回答
0

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

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

我没有注意到它是否被提及,但是 C# 4.0 引入了动态检查 VIAdynamic关键字。尽管我确定您会在不需要时避免使用它。

于 2009-12-29T18:12:50.167 回答
0

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

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

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

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

于 2013-06-14T18:16:42.670 回答
0

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

于 2015-05-07T08:15:56.977 回答