.NET 中的 readonly/const 在哪里?

发布于 2024-09-01 00:10:42 字数 266 浏览 9 评论 0原文

在 C++ 中,你会随处看到 void func(const T& t) 。然而,我在.NET 中还没有看到类似的东西。为什么?

我注意到使用 struct 的大量参数。但我没有看到带有 readonly/const 的函数。事实上,现在我尝试了它,我无法使用这些关键字来创建一个承诺不修改传入列表的函数。是否没有办法向调用者承诺该函数永远不会修改列表的内容?有没有办法说调用代码并说这个列表永远不应该被修改? (我知道我可以克隆列表或查看文档,但有时我喜欢编译错误)

In C++ you'll see void func(const T& t) everywhere. However, i havent seen anything similar in .NET. Why?

I have notice a nice amount of parameters using struct. But i see no functions with readonly/const. In fact now that i tried it i couldnt use those keywords to make a function that promises to not modify a list being passed in. Is there no way to promise the caller that this function will never modify the contents of list? Is there no way to say to call code and say this list should never be modified? (I know i can clone the list or look at documentation but i like compile errors sometime)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

半城柳色半声笛 2024-09-08 00:10:42

不变性仍然是 C# 正在成熟的一个领域。到目前为止,C# 还没有采用 C++ 的 const 语义……我实际上认为这是一件好事。 C++ 中 const 的行为常常使设计按您想要的方式工作的类层次结构变得具有挑战性。在不需要的地方,使用 const_cast<> 来绕过常量的代码并不罕见。希望 C# 的设计者能够发明一种更简单但仍然富有表现力的替代方案。

目前,没有语言功能可以将传递给方法的参数或对象标记为不可变。您能做的最好的事情就是使用只允许读取的接口(或者更好的是包装器)传递对象运营。

对于 .NET 中的某些标准集合,您可以使用 ReadOnlyCollection包装器,封装任何可变的 只读容器中的 ICollection 类型。

创建不可变类型需要规划和了解语言功能。例如,readonly 关键字是您的朋友。它允许您将类或结构的成员声明为不可变的。不幸的是,这种不变性仅适用于引用,而不适用于被引用对象的成员。这意味着您可以声明:

private readonly int[] m_Values = new int[100];

public void SomeMethod()
{
    m_Values = new int[50]; // illegal, won't compile!
    m_Values[10] = 42;      // perfectly legal, yet undesirable
}

在上面的示例中,对数组的引用是不可变的,但数组的各个元素不是。当然,这种行为不限于数组。

我发现在设计不可变类型时很有帮助的一种做法是将不可变行为分离到它自己的接口中,然后由管理数据的类实现。该接口仅公开保证不会改变对象状态的 get 属性和方法。然后可以将类型的实例作为该接口类型的参数传递给方法。 这是不变性支持的弱形式 - 因为被调用的方法通常可以将引用强制转换为可变类型。一个更好但更麻烦的替代方案是创建一个包装器实现,该实现实现相同的接口并维护对实际实例的引用(就像 ReadOnlyCollection 所做的那样)。 这需要更多工作,但为不变性提供了更强的保证。

您选择使用的方法取决于不变性保证的重要性,以及您愿意花费多少时间和精力来实现这一目标。

如果您有兴趣阅读有关此主题的更多信息,Eric Lippert 有一篇出色的 有关 C# 中不变性的系列文章

Immutability is still an area where C# is maturing. So far, C# has not adopted the const semantics of C++ ... which I actually think is a good thing. The behavior of const in C++ often made it challenging to design class hierarchies that worked they way you wanted. It wasn't uncommon to see code peppered with const_cast<> to bypass constness where it wasn't desirable. Hopefully, the designers of C# will invent a simpler but still expressive alternative.

At present, there is no language feature that marks parameters or objects passed to methods as immutable. The best you can do is pass an an object using an interface (or better yet a wrapper) that only permits read operations.

For some of the standard collection in .NET you can use the ReadOnlyCollection wrapper, which encapsulated any mutable ICollection type within a read-only container.

Creating immutable types requires planning and awareness of the language features. For example, the readonly keyword is your friend. It allows you to declare members of a class or struct as immutable. Unfortunately, this immutability only applies to the reference, not the members of the referenced object. What this means is that you can declare:

private readonly int[] m_Values = new int[100];

public void SomeMethod()
{
    m_Values = new int[50]; // illegal, won't compile!
    m_Values[10] = 42;      // perfectly legal, yet undesirable
}

In the above example, the reference to the array is immutable, but the individual elements of the array are not. This behavior extends beyond arrays, of course.

A practice I've found helpful when designing immutable types, is to separate the immutable behavior into its own interface which is then implemented by a class that manages the data. The interface only exposes get properties and methods that are guaranteed not to mutate the state of the object. It is then possible to pass instances of your type to methods as parameters of that interface type. This is a weak form of immutability support - since the called method can often cast the reference to the mutable type. A better, but more cumbersome alternative, is to create a wrapper implementation that implements that same interface and maintains a reference to the actual instance (much like ReadOnlyCollection does). This is more work but provides a stronger guarantee for immutability.

The approach you choose to use depends on how important guarantees of immutability are, and how much time and effort you are willing to spend to get there.

If you're interested in reading more on this topic, Eric Lippert has an excellent series of articles on immutability in C#.

朱染 2024-09-08 00:10:42

C# 中的方法参数没有 const 修饰符。如果您想拥有类似于 const 保证的东西,您可以在接口中使用不可变类型。例如,方法可以接受 IEnumerable 而不是可变集合类型。您还可以查看ReadOnlyCollection

There is no const modifier for method parameters in C#. If you want to have something similar to const guarantees you can use immutable types in your interfaces. For example, a method can accept an IEnumerable<T> instead of a mutable collection type. You can also look at ReadOnlyCollection.

音盲 2024-09-08 00:10:42

我注意到使用结构的大量参数。

这里值得一提的是,与 C++ 相比,C# 通过夸大值类型和引用类型之间的差异,夸大了结构和类之间的差异。在 C# 中,所有类都是引用类型,所有结构都是值类型。在 .Net 中,默认情况下一切都是按值传递的。

值类型的这种区别的结果是,所有值类型在传递给函数时都会被复制。如果将结构传递给函数,则可以保证该函数不会更改原始结构,因为该函数仅使用副本。将 const 添加到这样的参数是愚蠢的。

引用类型也是按值传递的。或者,更具体地说,引用本身是按值传递的。所以你有一个引用的副本,但它指向(引用)同一个对象。因此,函数对对象所做的更改将在函数退出后持续存在。

从表面上看,添加 const 选项(至少对于引用类型而言)似乎是个好主意。有点模糊的是副作用。或者更确切地说,这是如何执行的?显然,很容易说您的代码不能使用属性设置器。但其他方法呢?任何方法调用都可能需要更改对象。即使属性 getter 也可能会产生改变某些内容的副作用(假设您实现了一项安全功能来记录上次访问某些内容的时间)。您是否会因为副作用而拒绝对属性的读取访问?

I have notice a nice amount of parameters using struct.

One thing worth mentioning here is that C# exaggerates the difference between struct and class as compared to C++, by exaggerating the difference between value types and reference types. In C#, all classes are reference types, and all structs are value types. In .Net, everything is passed by value by default.

The result of this distinction for value types is that all value types are copied when passed to a function. If you pass a struct to a function, you are guaranteed that function will not change your original struct because the function is only working with a copy. Adding const to such a parameter is silly.

Reference types are passed by value, too. Or, more specifically, the reference itself is passed by value. So you have a copy of the reference, but it points to (refers to) the same object. Thus, changes made to the object by the function will persist after the function exits.

On surface, adding a const option, at least for reference types, seems like a good idea. Where it gets a little murky is with side effects. Or, rather, how is this enforced? Obviously it's easy enough to say that your code can't use property setters. But what about other methods? Any method call might need to change the object. Even property getters might have a side effect that changes something (say you implement a security feature to note when something was last accessed). Are you going to deny read access to a property because of the side effect?

朕就是辣么酷 2024-09-08 00:10:42

问题在于 C/C++ 中使用的 const 正确性仅由编译器强制执行。顺便说一句,很容易绕过。实际上,CLR(而不是编译器)在托管代码中强制执行类型安全。这是必然的,因为 .NET 框架支持多种语言。类型系统和交互规则在 CLI 中制定,这是一种需要服务于许多目标和主人的公共语言基础设施。

在当前语言中,常量正确性很少见。就我个人而言,我只知道 C++,这种语言移植到 CLI。对语法根本不相近的语言执行规则是很困难的。像无符号整数类型这样简单的东西不在 CLS 中,在基础组件的设计上留下了显着的印记。

不变性(真实的,不是编译器伪造的)让 MSFT 团队不断思考。它很受欢迎,我知道 C# 团队一直在考虑它。有利于并发等。 Eric Lippert 对此做了11 部分博客文章系列,不过有点逐渐消失了。对于一个人和他的观众来说太大了。如果有真正的行动来实施它,我相信他们会仔细考虑并使其发挥作用。有一天。一些语言。

The problem is that const correctness as used in C/C++ is only enforced by the compiler. And readily bypassed btw. The CLR actually enforces type safety in managed code, not the compiler. Necessarily so because the .NET framework supports many languages. The type system and interaction rules are laid out in the CLI, a common language infrastructure that needs to serve many goals and masters.

Const correctness is rare in current languages. Personally, I know of only C++, a language that is not ported to the CLI. Enforcing rules on languages that have nowhere near the syntax for them is difficult. Something as simple as unsigned integral types not being in the CLS left a notable mark on the design of the base assemblies.

Immutability (real, not faked with a compiler) keeps the MSFT teams thinking. It is popular, I know the C# team has been thinking about it. Good for concurrency, etcetera. Eric Lippert did a 11 part blog post series on it, kinda petered out though. Too big for one guy and his audience. If there will be a real move to getting it implemented, I trust them to think it through and make it work. Some day. Some language.

傾旎 2024-09-08 00:10:42

据我所知,这不可能通过简单的方法实现。也许这篇文章会给您一些想法:

http://www.c- Sharpcorner.com/UploadFile/bulentozkir/PassingConstInCS11082005014622AM/PassingConstInCS.aspx

as I know this is not possible on a easy way. Maybe this article gives you some ideas:

http://www.c-sharpcorner.com/UploadFile/bulentozkir/PassingConstInCS11082005014622AM/PassingConstInCS.aspx

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文