C # 中的“ const 正确性”

常量正确性的目的是提供一个用户无法修改或删除的实例视图。编译器通过指出何时从常量函数中中断常量,或尝试使用常量对象的非常量函数来支持这一点。那么,在不复制 const 方法的情况下,我能否在 C # 中使用一种目的相同的方法呢?

我知道不可变性,但是它并没有真正延伸到容器对象,只是举了一个例子。

16973 次浏览

C # 没有这样的特性。可以通过值或引用传递参数。除非指定 Ref = “ http://msdn.microsoft.com/en-us/library/14akc2c7(VS. 71) .aspx”rel = “ nofollow noReferrer”> ref 修饰符,否则引用本身是不可变的。但是引用的数据不是不可变的。所以如果你想避免副作用,就要小心。

MSDN:

传递参数

为了获得常量疯狂性(或函数式编程术语中的纯粹性)的好处,您需要以一种不可变的方式设计类,就像 c # 的 String 类一样。

这种方法比仅仅将对象标记为只读要好得多,因为使用不可变的类,您可以在多任务环境中轻松地传递数据。

  • 康斯特关键字可用于编译时常量,如基元类型和字符串
  • 只读关键字可用于诸如引用类型之类的运行时常量

只读的问题在于它只允许引用(指针)为常量。被引用(指向)的事物仍然可以被修改。这是棘手的部分,但没有办法绕过它。要实现常量对象意味着不让它们公开任何可变的方法或属性,但这很棘手。

参见 有效的 C # : 50种改进 C # 的具体方法(第2项-喜欢只读到 const。)

我也遇到过这个问题很多次,最终使用的是接口。

我认为重要的是要放弃 C # 是任何形式,甚至是 C + + 的进化的想法。它们是两种语言,语法几乎相同。

我通常在 C # 中通过定义一个类的只读视图来表达“ const 正确性”:

public interface IReadOnlyCustomer
{
String Name { get; }
int Age { get; }
}


public class Customer : IReadOnlyCustomer
{
private string m_name;
private int m_age;


public string Name
{
get { return m_name; }
set { m_name = value; }
}


public int Age
{
get { return m_age; }
set { m_age = value; }
}
}

接口就是答案,实际上它比 C + + 中的“ const”更强大。Const 是一个一刀切的解决方案,解决了“ const”被定义为“不设置成员或调用设置成员的东西”的问题。在许多场景中,这是一个很好的常量简写,但并非所有场景都是如此。例如,考虑一个函数,它基于某些成员计算一个值,但也缓存结果。在 C + + 中,这被认为是非常数,尽管从用户的角度来看它本质上是常数。

接口使您在定义希望从类中提供的特定功能子集时具有更大的灵活性。想要康斯坦斯吗?只提供一个没有变异方法的接口。想要允许设置一些东西而不是其他的吗?只提供这些方法的接口。

我只是想提醒你,许多系统。收款。泛型容器有一个 AsReadOnly 方法,它将返回一个不可变的集合。

同意其他一些方法,使用在构造函数中初始化的只读字段来创建不可变对象。

    public class Customer
{
private readonly string m_name;
private readonly int m_age;


public Customer(string name, int age)
{
m_name = name;
m_age = age;
}


public string Name
{
get { return m_name; }
}


public int Age
{
get { return m_age; }
}
}

或者,您也可以在属性上添加访问范围,即 public get 和 protected set?

    public class Customer
{
private string m_name;
private int m_age;


protected Customer()
{}


public Customer(string name, int age)
{
m_name = name;
m_age = age;
}


public string Name
{
get { return m_name; }
protected set { m_name = value; }
}


public int Age
{
get { return m_age; }
protected set { m_age = value; }
}
}