关于C#:如何在第二个例子中使用readonly修饰符来实现类的直角三角形部分?


How to use readonly modifier to implement right triangle portion of class in second examples?

本问题已经有最佳答案,请猛点这里访问。

下面是两个不同的例子,从本书插图C 2012年。在第一个例子中,斜边被声明为readonly。在第二个示例中,PInumberofsides声明为readonly。为什么PI赋值而numberofsides不赋值?

是否可以使用const来声明PI并为其赋值?假设我想在第二个例子中实现类形状的直角三角形部分。它如何处理numberofsides已经声明,并且双方没有赋值。我是说,我怎样才能知道斜边在哪一边?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
class RightTriangle
{
   public double A = 3;
   public double B = 4;

   public double Hypotenuse // Read-only property
   {
      get{ return Math.Sqrt((A*A)+(B*B)); } // Calculate return value
   }
}

class Program
{
   static void Main()
   {
      RightTriangle c = new RightTriangle();
      Console.WriteLine("Hypotenuse: {0}", c.Hypotenuse);
   }
}

class Shape
{
    // Keyword Initialized
    // ↓?↓
    readonly double PI = 3.1416;
    readonly int NumberOfSides;
    // ↑?↑

    // Keyword Not initialized
    public Shape(double side1, double side2) // Constructor
    {

        // Shape is a rectangle
        NumberOfSides = 4;
        // ↑
        // ... Set in constructor
    }
    public Shape(double side1, double side2, double side3) // Constructor
    {
        // Shape is a triangle
        NumberOfSides = 3;
        // ↑
        // ... Set in constructor
    }
}


常量实际上嵌入到程序集的元数据中。如果有人引用了您的常量,它也会被复制过来以提高性能。一般规则是永远不要对可能发生更改的值使用公共常量,因此Math.PI是一个常量。但不是double.Zero。常量不能是引用类型,只能是值类型。

使用static readonly可以解决这个问题,因为它可以在运行时分配,因此永远不会以相同的方式存储值。当然,您可以将其预先设置为一个值,但不同的是,外部应用程序不会获取分配的值并复制它。

另一个区别是,在运行时不能为const赋值。readonly可以更改,但只能在构造函数中更改。这就是为什么属性不能用readonly标记,但可以通过公共get和私有只读字段进行编码,使其工作起来与实际工作一样。

为了回答您的问题,我将把PI标记为常量,或者使用Math.PI。我还想说,你尝试的模式不够灵活,无法满足你的需要。形状(2D?)应该是一个抽象类,并且具有像getArea、getPermimeter这样的方法,以及像长度和高度这样的属性。然后将形状子类化为具体形状,如直角、圆、正方形。这些子类可以有自己的构造函数来初始化特定的构造函数。

看看这个或继承结构的工厂模式。这种模式是一个教科书上的例子。