const-correctness的要点是能够提供用户无法更改或删除的实例视图。编译器支持这一点,指出何时从const函数中断开constness,或者尝试使用const对象的非const函数。因此,如果不复制const方法,我可以在C#中使用具有相同目的的方法吗?
我知道不变性,但这并没有真正地将容器对象转移到一个例子。
答案 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:
答案 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)
readonly 的问题在于它只允许引用(指针)保持不变。引用(指向)的东西仍然可以修改。这是棘手的部分,但没有办法解决它。实现常量对象意味着不要让它们暴露任何可变方法或属性,但这很尴尬。
另见Effective C#: 50 Specific Ways to Improve Your C#(第2项 - 首选,只读const)。