且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何声明静态只读对象,但保持字段在c#中不变?

更新时间:2023-02-08 15:14:58

一种方法是从只有只读成员的接口派生。而你将常量的类型改为该界面的类型。



One way to do it is to derive from an interface with only read-only members. And you change the type of the "constant" to be the type of that interface instead.

interface IPointXY
{
  float X { get; }
  float Y { get; }
}

public class PointXY : Point2D, IPointXY 
{
  public static readonly IPointXY ORIGIN = new PointXY();
  //.... Other stuff as before
}



如果你有其他函数可以修改主类中的对象,你甚至可以决定使用另一个类来实现那些常量。



请注意,您必须在代码中使用界面而不是类。



另一种选择是永远不允许修改它创建后的一点。这是某些.NET类型使用的选项,如 string DateTime 等等。


我使用私有的setter作为属性:



I use private setters for the properties:

public class Point
{
  public int X { get ; private set ; }
  public int Y { get ; private set ; }

  public Point
  ( int X
  , int Y 
  )
  {
    this.X = X ;
    this.Y = Y ;
  } 

  public Point() : this ( 0 , 0 ){}

  public Point ( Point Source ) : this ( Source.X , Source.Y ){}
}


虽然Java有一个'Point2D结构,但据我所知,C#没有。



C#有'Point'和'PointF。 'PointF是密封的,所以你不能继承它。但是,假设您希望能够处理整数C#Point和其他数字类型C#类型,您可以执行以下操作:
While Java has a 'Point2D structure, to my knowledge, C# does not.

C# has 'Point, and 'PointF. 'PointF is sealed, so you can't inherit from it. However, assuming you want to be able to handle both integer C# Point, and other numeric-Type C# Types, you can do something like this:
public class PointXY<T> where T :
    // see Jon Skeet:
    // http://***.com/a/7690962/133321
    struct,
    IComparable,
    IFormattable,
    IConvertible,
    IComparable<T>,
    IEquatable<T>
{
    private static PointXY<T> _origin;
    public static PointXY<T> Origin
    {
        private set { _origin = value; }
        get { return _origin; }
    }

    // must have parameterless 'ctor
    public PointXY()
    {
    }

    public PointXY(T ox, T oy)
    {
        if (Origin == null)
        {
            Origin = new PointXY<T>();
            Origin.X = ox;
            Origin.Y = oy;
        }
    }

    private T _x;
    public T X
    {
        get { return _x; }
        set { _x = value; }
    }

    private T _y;
    public T Y
    {
        get { return _y; }
        set { _y = value; }
    }
}

考虑这个测试的结果,但是:

Consider the result of this test, however:

PointXY<int> p1 = new PointXY<int>(32, 99);
PointXY<int> p1a = new PointXY<int>(132, 199);
PointXY<double> p2 = new PointXY<double>(23.4, 32.4);

Console.WriteLine("{0} {1}, {2}", p1.Origin, p1.Origin.X, p1.Origin.Y);
Console.WriteLine("{0} {1}, {2}", p1a.Origin, p1a.Origin.X, p1a.Origin.Y);      
Console.WriteLine("{0} {1}, {2}", p2.Origin, p2.Origin.X, p2.Origin.Y);

// in Console:
PointXY`1[System.Int32] 32, 99
PointXY`1[System.Int32] 32, 99
PointXY`1[System.Double] 23.4, 32.4</double></double></int></int></int></int>

您会注意到,在此代码中,一旦您为某个特定类型设置了原点,那么你无法重置它。这可能不是你想要的,但是可以很容易地添加某种覆盖来让'Origin根据某些标准重置。

You'll note that in this code, once you've set the 'Origin for one specific Type, then you can't reset it. That may not be what you want, but it would be easy enough to add some kind of over-ride to let the 'Origin be reset based on certain criteria.