Inside C#_Chapter1(04)
Classes and Members
类和成员
Like any object-oriented language, C# allows you to define classes. In C#, classes can contain members that include constants, fields, methods, properties, events, indexers, operators, instance constructors, destructors, static constructors, and nested type declarations. We’ll cover all these members in due time, and we’ll define classes themselves in much greater detail in Chapter 2 and Chapter 3, “Classes and Structs.” In our little “Hello, World” example, we have a single class named HelloWorldConsoleApp that contains a single member—a method named
和其他面向对象编程语言一样,C#允许你定义类。在C#种类可以包含以下成员常量(constants)、字段(field)、方法(method)、属性(property)、事件(event)、索引程序(indexer,等价于VB.NET中的默认属性)、操作符(operator),实现构造函数(constructor)、析构函数(destructor)、static构造器(satic,有的书翻译为静态,但是static的含义和C/C++中的static已经完全不一样,它等价于VB.NET中的Share成员)以及嵌套类型定义。
The Main Method
Main方法
Let’s take a look at the only method in our application,
让我们来考察在我们应用程序中唯一的方法:Main。每一个C#应用程序都必须在其中的一个类中定义Main方法。并不限定那一个类必须包含Main方法,只要需要你可以在你的应用程序中定义很多的的类,只要其中的一个类包含Main方法即可。另外,Main方法必须被定义为public和static的。
The public keyword—which is more thoroughly covered in Chapter 3—is an access modifier that tells the C# compiler that any code can call this method. The static modifier—also covered in Chapter 3—tells the compiler that the Main method is a global method and that the class doesn’t need to be instantiated for the method to be called. This restriction makes sense when you think about it because, otherwise, the compiler wouldn’t know how or when to instantiate your class. Because the method is static, the compiler stores its address as the entry point so that the .NET common language runtime knows where to begin executing your application.
public关键字(将在第3章中更为详细的解释)是一个访问修饰符,它向C#编译器指出任何代码都可以调用这个方法。static修饰符(也将在第3章中详细解释)告诉编译器Main方法是一个全局方法,类不需要实例化就可以直接调用它(用 类名.static成员名 语法调用,并且也只能这样使用static成员)。这一约束是非常有意义的,否则编译就不会知道怎样或何时去实例化类。因为方法是static的,所以编译器用指针存储其地址因此.NET通用语言运行时(CLR)就知道从何处开始执行你的应用程序。
The demonstration programs in this chapter show the Main method as returning void and not receiving any arguments. However, you can define your Main method to return a value and take an array of arguments. Chapter 3 covers these options, as well as how to iterate through the passed arguments to an application’s Main method.
本章的实例应用程序中的Main方法没有任何返回值,也不接收任何参数。但是你可以定义Main方法返回一个值和接收一组参数。在第3章将解释如何去做。
The System.Console.WriteLine Method
System.Console.WriteLine 方法
As you probably guessed, the System.Console.WriteLine method writes the specified string—followed by a line terminator—to the standard output device. In most cases, unless you do something fancy to change the output or use an editor that redirects the output to a window, the string will output in a console window. What isn’t so obvious is that the string literal being passed is technically a managed object. A managed object can be defined simply as an instance of a CTS-defined type. We’ll get into the common type system (CTS) and its supported types in Chapter 2. However, at this point, I’d like to stay at a somewhat higher level. I’ll dive into the details of how this application works a bit later in this chapter, in a section entitled “Inside ‘Hello, World.’”
也许你已经猜到了,System.Console.WriteLine方法是向标准输出设备写给定的字符串并在末尾添加一个新行符。在大多数情况下,除非你改变了输出或使用编辑器将输出重定向到一个窗口,否则字符串将输出到命令行窗口。显然字符串是作为一个与托管的对象被传送的。一个托管对象可以作为一个CTS已定义类型的实例而非常简单的被定义。我们将在第2章深入讨论通用类型系统(CTS)和它所支持的类型。然而,坦率的说,我不喜欢停留在某些较高的层面,在本章稍后的一个名为“深入‘Hello,World’”的小节中我将深入探讨这个应用程序时如何运行的细节。
Namespaces and the using Directive
命名空间和using指令
The .NET Framework SDK is organized into a hierarchical lattice of namespaces. This organization can result in some rather lengthy names when a desired class or type is nested several layers deep. Therefore, to save on typing, C# provides the using directive. Let’s look at an example of how this directive works. In our “Hello, World” application, we have the following line of code:
.Net Framework SDK被组织为一个命名空间的层次网格。这种结构将导致当需要一个被嵌套在一个很深的层次内的类或类型时需要很长的一个名字去描述它。因此为了减少键盘输入,C#提供了using指令。让我们通过一个例子来看这个命令是如何工作的。在我们的“Hello, World”应用程序中我们有如下一行代码:
System.Console.WriteLine("Hello, World");
Typing this once isn’t such a big deal, but imagine having to fully qualify every type or class in a large application. The using directive enables you to list a kind of search path. Thus, if the compiler can’t understand something you’ve typed, it will search the listed namespaces for the definition. When we incorporate the using directive, our example program looks like this:
输入这样一句代码不是很麻烦,但是想象一下在一个庞大的应用程序中对每一个类和类型都像这样必须使用完全限定的情形。Using指令能够让你列出一种搜索路径的列表。因而如果编译器不能理解你输入的字符,它将自动的为定义去搜索列表中的命名空间。当我们结合使用using指令,我们的实例程序可以像这样编写:
using System; namespace InsideCSharp{ class UsingDirectiveApp { static void Main () { Console.WriteLine("This an example of the " + "using directive."); } }} When the compiler parses the Console.WriteLine method, it will determine that the method is undefined. However, it will then search through the namespaces specified by the using directives and, upon finding the method in the System namespace, will compile the code without error.
当编译器分析Console.WriteLine方法时,它将检测到该方法没用被定义。然而,接着它将搜索你用using指令指定的命名空间,并且将在System命名空间中找到方法,将继续编译代码而不会产生错误。
Note that the using directive applies to namespaces and not classes. In our example, System is the namespace, Console is the class, and WriteLine is a static method belonging to Console. Therefore, the following code would be invalid:
注意,using指令用于命名空间而不是类。在我们的例子中,System是命名空间,Console是类,WriteLine是一个属于Console的static方法。因此下面的代码是无效的:
using System.Console; // ERROR Can't use a using // directive with a class. namespace InsideCSharp{ class UsingErrorApp { static void Main () { WriteLine("This application will not compile."); } }} Although you can’t specify a class in a using directive, the following variant of the using directive does enable you to create aliases for classes, which can sometimes prove very useful:
虽然你不能使用using指令指定一个类,但是用下面的using指令可以让你为类创建别名,有时这是非常有用的:
using alias = class Using this form of the using directive, you can write code such as the following:
利用using指令的这一用法,你可以像这样编写代码:
using output = System.Console; namespace InsideCSharp{ class UsingAliasApp { static void Main () { output.WriteLine("This an example of the using " + "alias directive"); } }} This gives you the flexibility to apply meaningful aliases to classes nested several layers deep in the .NET hierarchy, thus making your code a little easier to write and maintain.
通过为类应用别名,为使用在.NET层次中嵌套很深的类提供了灵活性,因而可以让你的代码更容易书写和维护。
Skeleton Code
骨架代码
Let’s look at skeleton code for most any C# application—code that illustrates a basic outline for a simple, no-frills C# application. (You might want to type this code into a file and save it to use as a template for other programs in this chapter.) The angle brackets denote where you need to supply information.
我们来考察大多数C#应用程序的骨架代码,一个简单的,不提供不必要的功能的C#应用程序的基本框架。(你可以把这些代码输入到一个文件中并将它保存起来作为本章的其他应用程序的一个模板。)尖括号指出你必须提供信息的位置。
using <namespace>
namespace <your optional namespace>
class <your class>
{
public static void
{
}
}
Class Ambiguity
类的歧义
When a type is defined in more than one referenced namespace, the compiler will issue an error denoting the ambiguity. Therefore, the following code won’t compile because the class C is defined in two namespaces that are referenced with the using directive:
当一个类型在多个被引用的命名空间中被定义,编译器会抛出一个指出歧义的异常。因此下面的代码不能完成编译,因为类C在两个被using指令引用的命名空间中被定义:
using A;
using B;
namespace A
{
class C
{
public static void foo()
{
System.Console.WriteLine("A.C.foo");
}
}
}
namespace B
{
class C
{
public static void foo()
{
System.Console.WriteLine("B.C.foo");
}
}
}
class MultiplyDefinedClassesApp
{
public static void
{
C.foo();
}
}
Even with namespaces and the using directive, you still might run into name collision problems. In these situations, simply fully qualify the type you’re addressing. Now let’s see how to write our little demo application by using the Visual Studio .NET development environment.
即便使用了using指令,你仍然不可避免冲突的问题。在这种情况下,最简单的解决办法就是直接用完全限定的方式引用它。现在让我们看一看如何用Visual Studio .NET开发环境来编写我们的示例应用程序。
浙公网安备 33010602011771号