82

const 正确性的重点是能够提供用户无法更改或删除的实例视图。编译器通过指出何时从 const 函数中破坏 const 或尝试使用 const 对象的非 const 函数来支持这一点。因此,在不复制 const 方法的情况下,有没有可以在 C# 中使用的具有相同目的的方法?

我知道不变性,但这并没有真正延续到容器对象的名称中,只是一个例子。

4

7 回答 7

63

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

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

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

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; }
    }
}
于 2008-09-22T13:19:36.140 回答
28

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

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

于 2008-09-22T10:45:44.840 回答
23

我只是想提醒您,许多 System.Collections.Generics 容器都有一个 AsReadOnly 方法,该方法将为您返回一个不可变的集合。

于 2008-09-23T13:40:33.990 回答
4

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

MSDN:

传递参数

于 2008-09-22T10:30:01.367 回答
2

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

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

于 2008-09-22T17:33:42.237 回答
2

同意其他人的观点,即使用您在构造函数中初始化的只读字段来创建不可变对象。

    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 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; }
    }
  }
于 2008-09-25T11:26:05.373 回答
1
  • const关键字可用于编译时常量,例如原始类型和字符串
  • readonly关键字可用于运行时常量,例如引用类型

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

另请参阅有效的 C#:50 种改进 C# 的特定方法(第 2 项 - 首选只读而不是 const。)

于 2008-09-22T12:32:18.483 回答