如何在c#中正确封装,使Main不能改变值

本文关键字:Main 不能 能改变 封装 | 更新日期: 2023-09-27 18:05:56

我有一个关于c#封装的看似简单的问题。

在我们的一次作业中,我们应该创建一个简单的二维坐标计算系统,并正确封装文件,这样我们就不能从Main方法中编辑点的位置或长度。

我创建了两个c#文件,即Line和Point。文件program。cs是给我们的,所以我们应该解决这个问题,我们不允许改变文件中的任何代码。我们应该封装的文件是Line.cs或Point.cs文件,这样Main方法就不能从那里编辑点的位置,例如写入p1.X = 0;。下面是我到目前为止写的文件:

Program.cs

using System;
using coordinationSystem;
class Program
{
    public static void Main()
    {
        Point p0 = new Point();
        Point p1 = new Point(-10, -10);
        Console.WriteLine("Point p0, position = (" + p0.X + ", " + p0.Y + ")");
        Console.WriteLine("Point p1, position = (" + p1.X + ", " + p1.Y + ")");
        Line theLine = new Line(p0, p1); //This is the correct line.
        outdata("Print 1 of the line", theLine);
        p1.X = 0; //This is the thing I'm trying to prevent...
        outdata("Print 2 of the line", theLine);
        Point startposition = theLine.Position();
        startposition.Y = 5; //... same with this one
        outdata("Print 3 of the line", theLine);
    }
    private static void outdata(string text, Line theLine)
    {
        double length = theLine.Length();
        Point startPos = theLine.Position();
        Console.WriteLine("'n" + text);
        Console.WriteLine("==================================");
        Console.WriteLine("Length = {0 :f4} units", length);
        Console.WriteLine("Position = ({0},{1})", startPos.X, startPos.Y);
        Console.WriteLine("----------------------------------");
    }
}

Point.cs

namespace coordinationSystem
{
    public class Point
    {
        private int x, y;
        public Point() : this(0, 0) { } //Default-constructor.
        public Point(int X, int Y) //Constructor.
        {
            this.X = X;
            this.Y = Y;
        }
        public int X //Property for the X-coordinate.
        {
            get { return x; }
            set
            {
                x = value;
            }
        }
        public int Y //Property for the Y-coordinate.
        {
            get { return y; }
            set
            {
                y = value;
            }
        }
    }
}

Line.cs

using System;
namespace coordinationSystem
{
    public class Line
    {
        private Point p0;
        private Point p1;
        public Line(Point p0, Point p1)
        {
            this.p0 = p0;
            this.p1 = p1;
        }
        public double Length()
        {
            double pointLength = Math.Sqrt(Math.Pow(p0.X - p1.X, 2) + Math.Pow(p0.Y - p1.Y, 2));
            return pointLength;
        }
        public Point Position()
        {
            return p0;
        }
    }
}

我得出的结论是,我可能应该使用getset,但这并没有为我工作,因为Main中的theLine.Position();是一个方法(正如我之前写的,我们不应该编辑Program.cs/Main)。

有什么想法吗?任何帮助将非常感激!

编辑:

这是分配文本(从瑞典语粗略翻译):

考虑是否有可能破坏线路,如果你有访问对行和端点的引用。发生了什么?例如,如果您要更改Main中的p0或p1方法在创建行之后?当这条线发生了什么你在Main方法中移动起始位置吗?修改中的代码类线和点,以避免上述问题

如何在c#中正确封装,使Main不能改变值

这个问题有多种解决方案,这里有两个:

1-转换点到结构体。

结构是按值传递的,而不是按引用传递的,所以当你在方法上返回p0时,它将是一个副本,如果有人改变了返回点,原始行将保持不变。

2-复制点

不直接返回p0,只返回new Point(p0)。X, p . y),它将得到与1

相同的结果

无论如何,试着让你的老师被解雇,她不懂c#,她只懂Java,因此她不理解属性是如何工作的,因为任何c#程序员都会使用属性而不是函数从更高的类(如Line)中检索属性。

编辑:如果你使用方法2,那么也克隆在Line: 的构造函数上使用的点
    public Line(Point p0, Point p1)
    {
        this.p0 = new Point(p0.X, p0.Y);
        this.p1 = new Point(p1.X, p0.Y);
    }

由于无法更改Main()中明显损坏的代码,因此基本上只有两个选项:

    set访问器中抛出异常。
  1. set访问器中不做任何操作(也就是说,不实际更改值)。

它看起来像这样

public int X {
    get {
        return x;
    }
    set {
        // do nothing
    }
}

或:

public int X {
    get {
        return x;
    }
    set {
        throw new Exception("Cannot change value of X");
    }
}

对于Y和其他属性也可以这样做。

修改类中的代码Line和Point,使上述问题是避免。

为了避免从Main方法访问的问题,最好在编译时防止它,因此所需的修改如下:

使用private set的属性:

public int X //Property for the X-coordinate.
{
    get { return x; }
    private set
    {
        x = value;
    }
}
public int Y //Property for the Y-coordinate.
{
    get { return y; }
    private set
    {
        y = value;
    }
}

使用与y属性相同。

公共类点{

    public Point() : this(0, 0) { } //Default-constructor.
    public Point(int X, int Y) //Constructor.
    {
        //this.X = X;
        //this.Y = Y;
        setx(X);
        //this.y = Y;
    }
    public int X //Property for the X-coordinate.
    {
        get { return x; }
        private set
        {
            x = value;
        }
    }
    public int Y //Property for the Y-coordinate.
    {
        get { return y; }
    }
    public int setx(int Xvalue)
    {
        return x = Xvalue;
    }
}