定义封装的类类型 笔记

As soon as you define a custom constructor, the default constructor is silently removed from the class and is no longer available!

Therefore, if you wish to allow the object user to create an instance of your type with the default constructor, as well as your custom constructor, you must explicitly redefine the default.

一旦定义了自定义构造函数,默认构造函数就被自动从类中移除,并且不再有效!

因此,如果希望对象用户使用默认构造函数和自定义构造函数创建类型实例,就必须显示重新定义默认构造函数。

Note It is a compiler error to use the this keyword within the implementation of a static member. As you will see, static members operate on the class (not object) level, and therefore at the class level, there is no current object (thus no this)!

说明  在静态方法的实现中使用this关键字会产生编译错误。我们知道,静态成员在类(而不是对象)级别产生作用,因此在类级别没有当前对象(也就没有this)!

Chaining Constructor Calls Using this

class Motorcycle
{
    public int driverIntensity;
    public string driverName;
    // Constructor chaining.
    public Motorcycle() {}
    public Motorcycle(int intensity)
    : this(intensity, "") {}
    public Motorcycle(string name)
    : this(0, name) {}
    // This is the 'master' constructor that does all the real work.
    public Motorcycle(int intensity, string name)
    {
        if (intensity > 10)
        {
            intensity = 10;
        }
        driverIntensity = intensity;
        driverName = name;
    }
    ...
}

Using this technique you can simplify your programming tasks, as the real work is delegated to a single constructor (typically the constructor that has the most parameters), while the other constructors simply “pass the buck.”

使用this进行串联构造函数调用

class Motorcycle
{
    public int driverIntensity;
    public string driverName;
    // 构造函数链
    public Motorcycle() {}
    public Motorcycle(int intensity)
    : this(intensity, "") {}
    public Motorcycle(string name)
    : this(0, name) {}
    //这是做所有工作的”主”构造函数。
    public Motorcycle(int intensity, string name)
    {
        if (intensity > 10)
        {
            intensity = 10;
        }
        driverIntensity = intensity;
        driverName = name;
    }
    ...
}

使用这项技术可以简化编程任务,因为真正的工作都交给了一个构造函数(通常这个构造函数有大多数的参数)来做,而其他构造函数只是在”踢皮球”(推卸责任)。

// Make a Motorcycle.
Motorcycle c = new Motorcycle(5);

As you can see, the flow of constructor logic is as follows:

• We create our object by invoking the constructor requiring a single int.

• This constructor forwards the supplied data to the master constructor and provides any additional startup arguments not specified by the caller.

• The master constructor assigns the incoming data to the object’s field data.

• Control is returned to the constructor originally called, and executes any remaining code statements.

// 创建 Motorcycle.
Motorcycle c = new Motorcycle(5);

我们可以看到,构造函数的逻辑流程如下:

  • 通过调用只有单个int参数的构造函数来创建对象。
  • 构造函数将提供的数据转发给主构造函数,并且提供调用者没有提供的其他初始参数。
  • 主构造函数把传入的数据赋值给对象的字段数据。
  • 控制返回到最初调用的构造函数,并且执行所有剩余代码语句。

What if the value for your static data needed to be obtained from a database or external file?  For this very reason, C# allows you to define a static constructor:

class SavingsAccount
{
    public double currBalance;
    public static double currInterestRate;
    public SavingsAccount(double balance)
    {
        currBalance = balance;
    }
    // A static constructor.
    static SavingsAccount()
    {
        Console.WriteLine("In static ctor!");
        currInterestRate = 0.04;
    }
    ...
}

Simply put, a static constructor is a special constructor that is an ideal place to initialize the values of static data when the value is not known at compile time (e.g., you need to read in the value from an external file, generate a random number, etc.). Here are a few points of interest regarding static constructors:

• A given class (or structure) may define only a single static constructor.

• A static constructor does not take an access modifier and cannot take any parameters.

• A static constructor executes exactly one time, regardless of how many objects of the type are created.

• The runtime invokes the static constructor when it creates an instance of the class or before accessing the first static member invoked by the caller.

• The static constructor executes before any instance-level constructors.

如果静态数据值需要从数据库或外部文件获取,该怎么办呢?由于这个特殊原因,C#允许我们定义静态构造函数:

class SavingsAccount
{
    public double currBalance;
    public static double currInterestRate;
    public SavingsAccount(double balance)
    {
        currBalance = balance;
    }
    // 静态构造函数.
    static SavingsAccount()
    {
        Console.WriteLine("In static ctor!");
        currInterestRate = 0.04;
    }
    ...
}

简而言之,静态构造函数是特殊的构造函数,并且非常适用于初始化在编译时未知的静态数据的值(例如,我们需要从外部文件读取值或者生产随机数等)。这里是有关静态构造函数有趣的几点:

  • 一个类(或结构)只可以定义一个静态构造函数。
  • 静态构造函数不允许访问修饰符并且不能接受任何参数。
  • 无论创建了多少类型的对象,静态构造函数只执行一次。
  • 运行库创建类实例或调用者首次访问静态成员之前,运行库会调用静态构造函数。
  • 静态构造函数的执行先于任何实例级别的构造函数。

When a class has been defined as static, it is not creatable using the new keyword, and it can contain only members or fields marked with the static keyword.

如果一个类被定义为静态类的,就不能使用new关键字来创建,并且只能包含用static关键字标记的成员或字段.

The Default Access Modifiers

By default, type members are implicitly private while types are implicitly internal. Thus, the following class definition is automatically set to internal, while the type’s default constructor is automatically set to private:

// An internal class with a private default constructor.
class Radio
{
    Radio() { }
}

默认的访问修饰符

默认情况下,类型成员是隐式private的,而类型是隐式internal的.因此,如下的类定义自动设置为internal的,而类型的默认构造函数自动设置为private的.

// 具有私有默认构造函数的内部类.
class Radio
{
    Radio() { }
}


Nested Types

public class SportsCar
{
    // OK!  Nested types can be marked private.
    private enum CarColor
    {
        Red, Green, Blue
    }
}

Here, it is permissible to apply the private access modifier on the nested type. However, nonnested types (such as the SportsCar) can only be defined with the public or internalmodifiers. Therefore, the following class definition is illegal:

// Error! Nonnested types cannot be marked private!
private class SportsCar
{ }

嵌套类型

public class SportsCar
{
    // OK!  嵌套类型可以标记为private.
    private enum CarColor
    {
        Red, Green, Blue
    }
}

在这里,我们可以在嵌套类型上应用private访问修饰符.然而,非嵌套类型(如SportsCar)只能用public或internal修饰符定义.因此,如下类定义是不合法的:

// 错误!非嵌套类型不能被标记为私有的!
private class SportsCar
{ }


Constant fields of a class or structure are implicitly static.

类或结构的常量字段是隐式静态的.

Regardless of where you define a constant piece of data, the one point to always remember is that the initial value assigned to the constant must be specified at the time you define the constant.

class MyMathClass
{
    // Try to set PI in ctor?
    public const double PI;
    public MyMathClass()
    {
        // Error!
        PI = 3.14;
    }
}

The reason for this restriction has to do with the fact the value of constant data must be known at compile time.

不管在哪里定义常量,有一点我们需要记住,定义常量时必须为常量指定初始值.

class MyMathClass
{
    // 尝试在构造函数中设置PI?
    public const double PI;
    public MyMathClass()
    {
        // 错误!
        PI = 3.14;
    }
}

这种限制是因为在编译时必须知道常量的值.

Understanding Read-Only Fields

只读字段

Like a constant, a read-only field cannot be changed after the initial assignment. However, unlike a constant, the value assigned to a read-only field can be determined at runtime, and therefore can legally be assigned within the scope of a constructor (but nowhere else).

和常量相似,只读字段不能在赋初始值后改变.然而,和常量不同,赋给只读字段的值可以在运行时决定,因此在构造函数作用域中进行赋值是合法的(其他地方不行).

Unlike a constant field, read-only fields are not implicitly static. Thus, if you wish to expose PI from the class level, you must explicitly make use of the static keyword.

和常量字段不同,只读字段不是隐式静态的.因此,如果要从类级别公开PI(本例中的一个只读字段),就必须显示使用static关键字.

Understanding Partial Types

The only requirement when defining partial types is that the type’s name (Employee in this case) is identical and defined within the same .NET namespace.

部分类

定义部分类唯一的要求是,类名(在这里是Employee)必须是一致的并且定义在相同的.NET命名空间中.

原文地址:https://www.cnblogs.com/tangzhengyue/p/2520916.html