当前位置:  开发笔记 > 编程语言 > 正文

C#中的"const正确性"

如何解决《C#中的"const正确性"》经验,为你挑选了3个好方法。

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

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



1> Trap..:

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

我认为重要的是放弃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; }
    }
}


当然,但如果您的某个字段是List或富类型,该怎么办?您的解决方案很快变得复杂.
@Trap:这就是问题的重点.返回一个内部集合是一种不好的做法,因为外部世界可以修改你的内部结构,在C++中使用const解决:你提供了一个恒定的集合视图(不能添加/删除元素,只提供一个恒定的视图元素)因此它是安全的(和一个常见的习语).无需编制接口或其他技巧来避免外部代码更改内部.
值得注意的是,`const`-ness**是设计的一部分,它声明的意图与编写外部const接口一样清晰.此外,如果必须手动处理const-interfaces,则提供const-interfaces可能是一项复杂的任务,并且可能需要写入几乎与复合类型中存在的类一样多的接口.这将我们带到你最后的感觉:'由于忘记添加const而搞砸了'.更容易习惯在各处添加`const`(开发成本很小),而不是为每个类编写只读接口.
@Trap,我同意这个机制是对开发的一种帮助,其中包括检测开发人员的错误,无论是否有经验.我不同意必须编写只读接口是一个更好的解决方案.第一点是无论何时用C++编写类,都隐式定义了常量接口:成员子集声明为`const`,没有定义单独接口和需要运行时调度的额外成本.也就是说,该语言提供了一种实现编译时const接口的简单方法.
我真正喜欢C#的原因之一就是它没有像Java那样抛弃C++的所有实用功能.Java尝试用接口做所有事情,这是一场灾难.证据就在布丁中.随着时间的推移,很多功能被添加到Java中,最初被谴责为异端邪说.基于接口的设计已经占据了它的位置,但是当采用极端情况时,可能会不必要地使程序的架构复杂化.您最终会花费更多时间编写样板代码,而花费更少时间来完成有用的工作.
这不是那些有"答案"的问题之一,但我真的很喜欢这个解决方案.它很优雅,可以适应很多情况,而且写得很快.
我赞成"IReadableCustomer"作为接口的名称,而不是"IReadOnlyCustomer",因为后者在由"IReadWriteCustomer"继承时会暗示矛盾[如果接口名称的主要字符是小写的,我会使用"iMutableCustomer" ",但"IMutableCustomer"看起来太像"ImmutableCustomer"]
如果在自己的对象中包含足够大的可变对象,那么如何为包含对象提供只读接口?你会创建一个包含对象的副本吗?当你了解const引用有多强大时,这是你唯一想念的.

2> Sam..:

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

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


但是不变性并不能真正扩展到复杂的对象,或者它是什么?
我认为,如果你的对象如此复杂以至于不可能进行不可变性,你就有了很好的重构能力.
@tenpn:当完成正确时,不变性实际上非常好地扩展.真正有用的一件事是对大型不可变类型使用`Builder`类(Java和.NET定义了`StringBuilder`类,这只是一个例子).
不仅如此,但有些情况下你确实想要更改对象(对象确实发生变化!)但在大多数情况下仍然提供只读视图.不可变对象意味着无论何时需要进行更改(发生更改),您都需要创建一个除了更改之外的所有相同数据的新对象.考虑一所有学校教室的学校,学生......每次学生的出生日期和年龄变化时,你想创建一所新学校吗?或者你可以改变学生级别的年龄,房间级别的学生,也许是学校级别的学生?
我认为这是最好的一组.不可变对象的使用率很低.

3> Rick Mineric..:

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


即使ReadOnlyCollection <T>不是,T仍然是可变的,这仍然存在问题。
推荐阅读
pan2502851807
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有