如何声明静态只读对象,但保持字段在c#中不变? [英] How do I declare a static readonly object but keep the fields constant in c#?

查看:116
本文介绍了如何声明静态只读对象,但保持字段在c#中不变?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个基本的2d点类的以下代码:



I've got the following code for a basic 2d point class:

public class PointXY : Point2D
    {
        private float x, y;

        public static readonly PointXY ORIGIN = new PointXY();

        public PointXY()
        {  }

        public PointXY(float x, float y)
        {
            Set(x, y);
        }

        public float X
        {
            get { return x; }
            set { x = value; }
        }

        public float Y
        {
            get { return y; }
            set { y = value; }
        }
}





所以我希望ORIGIN x和y的值在x =保持不变0,y = 0。但是从主控制台,我仍然可以输入:





So I want the values of ORIGIN x and y to stay constant at x=0, y=0. But from the main console, I can still type :

PointXY a = PointXY.ORIGIN; // ok
a.X = 4; // shouldn't be ok 





甚至只是:





or even just:

PointXY.ORIGIN.X = 4; // shouldn't be ok





从纯粹的数学意义上讲,我不应该将ORIGIN的x和y值更改为0以外的其他值。如何在C#中执行此操作?我在这里遗漏了什么?



From a purely mathematical sense I shouldn't be able to change the values of x and y of the ORIGIN to be something other than its value of 0. How do I do this in C#? Am I missing something here?

推荐答案

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



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://stackoverflow.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.


这篇关于如何声明静态只读对象,但保持字段在c#中不变?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆