哪个声明更好?

时间:2009-04-28 13:21:14

标签: c# oop

我将在编程中改变我的C#风格(我一直在使用'public static'代表变量,方法 - 一切)。

我的问题:

public class WinSock
{
    public Socket sock;
    public byte[] data;
    .....
}

var data = new byte[2058];
data = WinSock.data;

或者这个:

private class WinSock
{
    private Socket sock;
    private byte[] data;
    .....
    public byte[] getdata()
    {
        get {return data;}
    }
}

WinSock ws = new WinSock();
var data = new byte[2058];
data = ws.getdata();

在这两种情况下,都可以从其他类访问数据和sock变量。

两个声明中哪一个更好?

9 个答案:

答案 0 :(得分:11)

通常,将字段公开并不是一个好主意。

由于getdata是一个属性,因此应该称为Data。

private class WinSock
{
    private Socket sock;
    private byte[] data;
    .....
    public byte[] Data
    {
        get { return data; }
    }
}

公共接口由公共属性和方法组成,应确保状态(字段)永远不会出现矛盾。该班负责这些领域。它不应该允许任何人直接写入它。这就是封装的内容。

答案 1 :(得分:4)

从纯粹的“宣言”方面来说,第二个稍微好一点。但是,从设计角度(以及从可见的角度来看),这并不好。具体来说,返回对类中私有字段的数组的引用是一个很大的禁忌。考虑:

private class WinSock
{
    private Socket sock;
    private byte[] data;
    .....

    // Read at most length bytes of data to buffer starting at offset
    // and return the number of bytes read
    public int Read(byte[] buffer, int offset, int length)
    {
        // ...
    }
}

WinSock ws = new WinSock();
var data = new byte[2058];
int bytesRead = ws.Read(data, 0, data.Length);

答案 2 :(得分:4)

第二个更接近通常被认为更好的东西。在面向对象编程中,我们将变量封装在类中,并且只在类外部尽可能少地公开。

使用首字母大写字母命名您的属性,并将其命名为数据成员而不是方法,即Data而不是getdata

public class WinSock {

    private Socket _socket;
    private byte[] _data;

    public Socket Socket {
       get { return _socket; }
    }

    public byte[] Data {
        get { return _data; }
    }

}

(命名私有成员变量的一种方法是使用下划线。还有一些常用的惯例,但重要的是选择一个并坚持下去。)

在C#3中,还有一个属性的快捷语法:

public class WinSock {

    public Socket Socket { get; private set; }

    public byte[] Data { get; private set; }

}

答案 3 :(得分:3)

第二个。它被称为“封装”。您隐藏并保护您的数据不受外界影响。

答案 4 :(得分:3)

  • 如果一个类是嵌套的,那么它只能是private - 然后访问仅限于外部类。 internal会更常见(并且是非嵌套类的默认值)
  • 请勿使用公共字段(public Socket sock;
  • 请考虑自动实施的属性(例如public Socket Socket {get; private set;}
  • 决定getdata是一种方法还是一种财产;-p

答案 5 :(得分:1)

怎么样:

public Socket Sock { get; private set; }
public byte[] Date { get; private set; }

如果getter和setter不需要任何验证逻辑,则自动实现的属性是可行的方法。这提供了封装,并允许您稍后在需要时将实现更改为手动实现的属性,而不强制重新编译引用您的.dll。

答案 6 :(得分:0)

不要使用GetMethod(),而应将私有字段包装在属性中。

public class WinSock
{
    private Socket sock;
    private byte[] data;

    public byte[] Data
    {
       get { return data; }
       set { data = value; }
    }
}

答案 7 :(得分:0)

我还要保证第二个代码位,修改后将字段包装到属性中并正确命名。因此,您可以将属性命名为“数据”而不是“getdata”。

答案 8 :(得分:0)

还有几点:

  1. 如果您计划对使用WinSock类的代码进行单元测试,则应考虑将该类设为public而不是internal,并考虑将这些方法设为虚拟。这种类通常需要被模拟或存根以将不同的数据返回给调用者,以便可以执行调用者代码中的不同路径。
  2. 您应该考虑如何构造此类的对象。例如,你是否会传入Socket,还是会将一些数据传递给类,以便它可以创建Socket?您的目标应该是传递在有用状态下创建对象所需的任何数据。
  3. 你应该考虑如何测试这门课程。特别是,这个类将如何获得它需要用来完成任务的任何其他类。为此,您应该搜索依赖注入。这将使你走上一条有用的道路。