const正确性的重点是能够提供用户无法更改或删除的实例的视图。编译器通过指出何时从const函数中破坏constness或尝试使用const对象的非const函数来支持此功能。因此,无需复制const方法,是否可以在C#中使用具有相同目的的方法?
我知道不变性,但这并没有真正延续到容器对象上,仅举一个例子。
const正确性的重点是能够提供用户无法更改或删除的实例的视图。编译器通过指出何时从const函数中破坏constness或尝试使用const对象的非const函数来支持此功能。因此,无需复制const方法,是否可以在C#中使用具有相同目的的方法?
我知道不变性,但这并没有真正延续到容器对象上,仅举一个例子。
const_cast
用C#实现呢?
Answers:
我也多次遇到这个问题,最终使用接口。
我认为重要的一点是,不要认为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; }
}
}
const
,而无需定义单独的接口并需要运行时调度。也就是说,该语言提供了一种实现编译时const接口的简单方法。
const
-ness是设计的一部分,它声明意图与编写外部const接口一样清晰。此外,如果必须手动处理,则提供const接口可能是一项复杂的任务,并且可能需要编写与复合类型中存在的类几乎一样多的接口。这将我们带到您的最后一个观点:“由于忘记添加const而弄乱了内容”。与const
为每个类编写只读接口相比,习惯于在各处添加内容(开发成本很小)要容易得多。
为了获得const-craziness(或函数式编程术语的纯净性)的好处,您将需要设计类以使其不可变,就像c#的String类一样。
这种方法比仅将对象标记为只读要好得多,因为使用不可变的类,您可以在多任务环境中轻松传递数据。
Builder
类用于大型不可变类型(Java和.NET定义了StringBuilder
该类,这只是一个示例)。
我只是想为您指出,许多System.Collections.Generics容器都有一个AsReadOnly方法,它将为您提供不可变的集合。
接口是答案,并且实际上比C ++中的“ const”更强大。const是解决“ const”定义为“不设置成员或不调用设置成员的东西”的问题的一刀切解决方案。在许多情况下,这是保持一致性的好捷径,但并非所有情况都如此。例如,考虑一个函数,该函数根据某些成员计算值,但也缓存结果。在C ++中,这被认为是非常量,尽管从用户的角度来看,它本质上是常量。
接口使您可以更灵活地定义要从类中提供的功能的特定子集。想要保持不变?只需提供没有任何变异方法的接口即可。是否要允许设置某些东西,而不允许设置其他东西?仅提供带有这些方法的接口。
mutable
。
与其他一些人达成共识后,他们会考虑使用在构造函数中初始化的只读字段来创建不可变对象。
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; }
}
}
只读的问题在于,它仅允许引用(指针)为常数。引用(指向)的内容仍可以修改。这是棘手的部分,但是没有办法解决。实现常量对象意味着使它们不公开任何可变的方法或属性,但这很尴尬。
另请参见有效的C#:50种改善C#的特定方法(第2项-首选只读而不是const)。