C#中的“const正确性”

时间:2008-09-22 10:25:31

标签: c# theory const-correctness

const-correctness的要点是能够提供用户无法更改或删除的实例视图。编译器支持这一点,指出何时从const函数中断开constness,或者尝试使用const对象的非const函数。因此,如果不复制const方法,我可以在C#中使用具有相同目的的方法吗?

我知道不变性,但这并没有真正地将容器对象转移到一个例子。

7 个答案:

答案 0 :(得分:62)

我也经常遇到这个问题并最终使用接口。

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

我通常通过定义类的只读视图来表达C#中的'const correctness':

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; }
    }
}

答案 1 :(得分:28)

为了获得const-craziness(或函数式编程术语中的纯粹)的好处,你需要以一种方式设计你的类,使它们是不可变的,就像c#的String类一样。

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

答案 2 :(得分:23)

我只想注意一下,许多System.Collections.Generics容器都有一个AsReadOnly方法,它会返回一个不可变的集合。

答案 3 :(得分:4)

C#没有这样的功能。您可以按值或引用传递参数。除非指定 ref 修饰符,否则引用本身是不可变的。但引用的数据不是一成不变的。所以如果你想避免副作用,你需要小心。

MSDN:

Passing Parameters

答案 4 :(得分:3)

接口是答案,实际上比C ++中的“const”更强大。 const是一个一刀切的解决方案,其中“const”被定义为“不设置成员或调用设置成员的东西”。在许多情况下,这是常量的良好速记,但不是全部。例如,考虑一个函数,该函数根据某些成员计算值,但也会缓存结果。在C ++中,这被认为是非const的,尽管从用户的角度来看它基本上是const。

接口使您可以更灵活地定义要从类中提供的特定功能子集。想要保持稳定吗?只提供一个没有变异方法的接口。想要允许设置一些东西而不是其他东西吗?提供仅具有这些方法的界面。

答案 5 :(得分:3)

同意其他一些人看看使用在构造函数中初始化的readonly字段来创建不可变对象。

    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; }
    }
  }

答案 6 :(得分:2)

  • const 关键字可用于编译时常量,例如基本类型和字符串
  • readonly 关键字可用于运行时常量,例如引用类型

readonly 的问题在于它只允许引用(指针)保持不变。引用(指向)的东西仍然可以修改。这是棘手的部分,但没有办法解决它。实现常量对象意味着不要让它们暴露任何可变方法或属性,但这很尴尬。

另见Effective C#: 50 Specific Ways to Improve Your C#(第2项 - 首选,只读const)。