C# 中的“常量正确性”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/114149/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 14:22:47  来源:igfitidea点击:

"const correctness" in C#

提问by tenpn

The point of const-correctness is to be able to provide a view of an instance that can't be altered or deleted by the user. The compiler supports this by pointing out when you break constness from within a const function, or try to use a non-const function of a const object. So without copying the const approach, is there a methodology I can use in C# that has the same ends?

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

I'm aware of immutability, but that doesn't really carry over to container objects to name but one example.

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

采纳答案by Trap

I've come across this issue a lot of times too and ended up using interfaces.

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

I think it's important to drop the idea that C# is any form, or even an evolution of C++. They're two different languages that share almost the same syntax.

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

I usually express 'const correctness' in C# by defining a read-only view of a class:

我通常在 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; }
    }
}

回答by aku

C# doesn't have such feature. You can pass argument by value or by reference. Reference itself is immutable unless you specify refmodifier. But referenced data isn't immutable. So you need to be careful if you want to avoid side effects.

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

MSDN:

微软:

Passing Parameters

传递参数

回答by Sam

To get the benefit of const-craziness (or pureness in functional programming terms), you will need to design your classes in a way so they are immutable, just like the String class of c# is.

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

This approach is way better than just marking an object as readonly, since with immutable classes you can pass data around easily in multi-tasking environments.

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

回答by Thomas Bratt

  • The constkeyword can be used for compile time constants such as primitive types and strings
  • The readonlykeyword can be used for run-time constants such as reference types
  • 常量关键字可以用于编译时间常量如基本类型和字符串
  • 所述只读关键字可以用于运行时间常量如引用类型

The problem with readonlyis that it only allows the reference (pointer) to be constant. The thing referenced (pointed to) can still be modified. This is the tricky part but there is no way around it. To implement constant objects means making them not expose any mutable methods or properties but this is awkward.

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

See also Effective C#: 50 Specific Ways to Improve Your C#(Item 2 - Prefer readonly to const.)

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

回答by munificent

Interfaces are the answer, and are actually more powerful than "const" in C++. const is a one-size-fits-all solution to the problem where "const" is defined as "doesn't set members or call something that sets members". That's a good shorthand for const-ness in many scenarios, but not all of them. For example, consider a function that calculates a value based on some members but also caches the results. In C++, that's considered non-const, although from the user's perspective it is essentially const.

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

Interfaces give you more flexibility in defining the specific subset of capabilities you want to provide from your class. Want const-ness? Just provide an interface with no mutating methods. Want to allow setting some things but not others? Provide an interface with just those methods.

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

回答by Rick Minerich

I just wanted to note for you that many of the System.Collections.Generics containers have an AsReadOnly method which will give you back an immutable collection.

我只是想提醒您注意,许多 System.Collections.Generics 容器都有一个 AsReadOnly 方法,它会给您一个不可变的集合。

回答by Stuart McConnell

Agree with some of the others look at using readonly fields that you initialize in the constructor, to create immutable objects.

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

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

Alternatively you could also add access scope on the properties, i.e. public get and 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; }
    }
  }