参数可以恒定吗?
我正在寻找 Java 的 final
的 C# 等效项。它存在吗?
C# 中是否有类似以下内容的内容:
public Foo(final int bar);
在上面的示例中,bar
是一个只读变量,无法通过 Foo()
进行更改。在 C# 中有什么办法可以做到这一点吗?
例如,也许我有一个很长的方法,它将处理某些对象(整数)的 x、y 和 z 坐标。我想绝对确定该函数不会以任何方式改变这些值,从而损坏数据。因此,我想将它们声明为只读。
public Foo(int x, int y, int z) {
// do stuff
x++; // oops. This corrupts the data. Can this be caught at compile time?
// do more stuff, assuming x is still the original value.
}
I'm looking for the C# equivalent of Java's final
. Does it exist?
Does C# have anything like the following:
public Foo(final int bar);
In the above example, bar
is a read only variable and cannot be changed by Foo()
. Is there any way to do this in C#?
For instance, maybe I have a long method that will be working with x
, y
, and z
coordinates of some object (ints). I want to be absolutely certain that the function doesn't alter these values in any way, thereby corrupting the data. Thus, I would like to declare them readonly.
public Foo(int x, int y, int z) {
// do stuff
x++; // oops. This corrupts the data. Can this be caught at compile time?
// do more stuff, assuming x is still the original value.
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
不幸的是,您无法在 C# 中执行此操作。
const
关键字只能用于局部变量和字段。readonly
关键字只能在字段上使用。来自 http://www.25hoursaday.com/CsharpVsJava.html
编辑(2019/08/13 ):
我将其放入以提高可见性,因为它已被接受并且在列表中名列前茅。现在可以使用
in
参数来实现。有关详细信息,请参阅下面的答案。Unfortunately you cannot do this in C#.
The
const
keyword can only be used for local variables and fields.The
readonly
keyword can only be used on fields.from http://www.25hoursaday.com/CsharpVsJava.html
EDIT (2019/08/13):
I'm throwing this in for visibility since this is accepted and highest on the list. It's now kind of possible with
in
parameters. See the answer below this one for details.现在,这在 C# 版本 7.2 中已成为可能:
您可以在方法签名中使用
in
关键字。 MSDN 文档。在指定方法的参数之前应添加
in
关键字。例如,C# 7.2 中的有效方法:
虽然不允许以下内容:
尝试修改
x
或y
时将显示以下错误,因为它们被标记为在:
用
in
标记参数意味着:This is now possible in C# version 7.2:
You can use the
in
keyword in the method signature. MSDN documentation.The
in
keyword should be added before specifying a method's argument.Example, a valid method in C# 7.2:
While the following is not allowed:
Following error will be shown when trying to modify either
x
ory
since they are marked within
:Marking an argument with
in
means:答案:C# 没有像 C++ 那样的 const 功能。
我同意贝内特·迪尔的观点。
const 关键字非常有用。在示例中,您使用了 int,但人们不明白您的意思。但是,为什么如果您的参数是一个用户巨大且复杂的对象,并且无法在该函数内更改呢?这就是 const 关键字的使用:参数不能在该方法内更改,因为[无论此处的原因]这对该方法并不重要。 Const 关键字非常强大,我真的很怀念 C# 中的它。
The answer: C# doesn't have the const functionality like C++.
I agree with Bennett Dill.
The const keyword is very useful. In the example, you used an int and people don't get your point. But, why if you parameter is an user huge and complex object that can't be changed inside that function? That's the use of const keyword: parameter can't change inside that method because [whatever reason here] that doesn't matters for that method. Const keyword is very powerful and I really miss it in C#.
这是一个简短而甜蜜的答案,可能会得到很多反对票。我还没有阅读所有的帖子和评论,所以如果之前有人建议过,请原谅我。
为什么不将参数传递给一个将它们公开为不可变的对象,然后在您的方法中使用该对象呢?
我意识到这可能是一个非常明显的解决方法,已经被考虑过,并且OP试图通过提出这个问题来避免这样做,但我觉得它应该在这里......祝你好运
:-)
Here's a short and sweet answer that will probably get a lot of down votes. I haven't read all of the posts and comments, so please forgive me if this has been previously suggested.
Why not take your parameters and pass them into an object that exposes them as immutable and then use that object in your method?
I realize this is probably a very obvious work around that has already been considered and the OP is trying to avoid doing this by asking this question, but I felt it should be here none-the-less...
Good luck :-)
我将从
int
部分开始。int
是一种值类型,在 .Net 中这意味着您实际上正在处理一个副本。告诉一个方法“你可以拥有这个值的副本。这是你的副本,不是我的;我再也不会看到它了。但你不能更改副本”,这是一个非常奇怪的设计约束。在方法调用中隐含的是复制这个值是可以的,否则我们无法安全地调用该方法。如果该方法需要原件,则留给实现者复制一份保存。要么为该方法提供值,要么不为该方法提供值。不要在这两者之间表现得软弱无力。让我们继续讨论引用类型。现在有点令人困惑。您是指引用本身无法更改的常量引用,还是完全锁定的、不可更改的对象?如果是前者,.Net 中的引用默认按值传递。也就是说,您将获得参考的副本。所以我们的情况本质上与值类型相同。如果实施者需要原始参考,他们可以自己保留。
这只会给我们留下不变的(锁定/不可变的)对象。从运行时的角度来看,这似乎没问题,但是编译器如何强制执行它呢?由于属性和方法都可能产生副作用,因此您基本上只能进行只读字段访问。这样的物体不太可能很有趣。
I'll start with the
int
portion.int
is a value type, and in .Net that means you really are dealing with a copy. It's a really weird design constraint to tell a method "You can have a copy of this value. It's your copy, not mine; I'll never see it again. But you can't change the copy." It's implicit in the method call that copying this value is okay, otherwise we couldn't have safely called the method. If the method needs the original, leave it to the implementer to make a copy to save it. Either give the method the value or do not give the method the value. Don't go all wishy-washy in between.Let's move on to reference types. Now it gets a little confusing. Do you mean a constant reference, where the reference itself cannot be changed, or a completely locked, unchangeable object? If the former, references in .Net by default are passed by value. That is, you get a copy of the reference. So we have essentially the same situation as for value types. If the implementor will need the original reference they can keep it themselves.
That just leaves us with constant (locked/immutable) object. This might seem okay from a runtime perspective, but how is the compiler to enforce it? Since properties and methods can all have side effects, you'd essentially be limited to read-only field access. Such an object isn't likely to be very interesting.
为您的类创建一个仅具有只读属性访问器的接口。然后让您的参数属于该接口而不是类本身。示例:
对于结构,创建一个通用 const 包装器。
但值得注意的是,您想要对结构执行您要求执行的操作,这很奇怪,作为方法的编写者,您应该期望知道该方法中发生了什么。它不会影响传入的值以在方法中修改它们,因此您唯一关心的是确保您在编写的方法中表现良好。到了某个时候,警惕和干净的代码就成为关键,而不是强制执行 const 和其他类似的规则。
Create an interface for your class that has only readonly property accessors. Then have your parameter be of that interface rather than the class itself. Example:
For structs, create a generic const wrapper.
Its worth noting though, that its strange that you want to do what you're asking to do regarding structs, as the writer of the method you should expect to know whats going on in that method. It won't affect the values passed in to modify them within the method, so your only concern is making sure you behave yourself in the method you're writing. There comes a point where vigilance and clean code are the key, over enforcing const and other such rules.
我知道这可能有点晚了。其中 T :结构。班级。的值,这将强制编译器错误。类型。
但对于仍在寻找其他方法的人来说,可能还有另一种方法可以绕过 C# 标准的这一限制。
我们可以编写包装类 ReadOnly
隐式转换为基类型 T。
但只有显式转换为wrapper
如果开发人员尝试隐式设置为 ReadOnly
我将在下面演示两种可能的用途。
用法 1 需要更改调用者定义。此用法仅用于测试“TestCalled”函数代码的正确性。在发布级别/构建时,您不应该使用它。因为在大规模数学运算中可能会过度转换,并使代码变慢。我不会使用它,但出于演示目的,我发布了它。
我建议的用法 2 在 TestCalled2 函数中演示了调试与发布的使用。使用此方法时,TestCaller 函数中也不会进行转换,但需要使用编译器条件对 TestCaller2 定义进行更多编码。您可以注意到调试配置中的编译器错误,而在发布配置中 TestCalled2 函数中的所有代码都将成功编译。
I know this might be little late.
But for people that are still searching other ways for this, there might be another way around this limitation of C# standard.
We could write wrapper class ReadOnly<T> where T : struct.
With implicit conversion to base type T.
But only explicit conversion to wrapper<T> class.
Which will enforce compiler errors if developer tries implicit set to value of ReadOnly<T> type.
As I will demonstrate two possible uses below.
USAGE 1 required caller definition to change. This usage will have only use in testing for correctness of your "TestCalled" functions code. While on release level/builds you shouldn't use it. Since in large scale mathematical operations might overkill in conversions, and make your code slow. I wouldn't use it, but for demonstration purpose only I have posted it.
USAGE 2 which I would suggest, has Debug vs Release use demonstrated in TestCalled2 function. Also there would be no conversion in TestCaller function when using this approach, but it requires a little more of coding of TestCaller2 definitions using compiler conditioning. You can notice compiler errors in debug configuration, while on release configuration all code in TestCalled2 function will compile successfully.
如果您经常遇到这样的麻烦,那么您应该考虑“匈牙利应用程序”。好的类型,而不是坏的类型。虽然这通常不会尝试表达方法参数的恒定性(这太不寻常了),但肯定没有什么可以阻止您在标识符名称之前添加额外的“c”。
对于所有现在渴望按下否决按钮的人,请阅读这些名人对这个主题的看法:
If you often run into trouble like this then you should consider "apps hungarian". The good kind, as opposed to the bad kind. While this doesn't normally tries to express constant-ness of a method parameter (that's just too unusual), there is certainly nothing that stops you from tacking an extra "c" before the identifier name.
To all those aching to slam the downvote button now, please read the opinions of these luminaries on the topic:
如果 struct 被传递到方法中,除非它是通过 ref 传递的,否则它不会被传递到的方法更改。所以从这个意义上说,是的。
您是否可以创建一个参数,其值无法在方法内分配,或者其属性无法在方法内设置?不可以。您无法阻止在方法内分配值,但可以通过创建不可变类型来阻止设置其属性。
问题不在于参数或其属性是否可以在方法内分配。问题是当该方法退出时会发生什么。
任何外部数据唯一会被更改的情况是,如果您传入一个类并更改其属性之一,或者如果您使用 ref 关键字传递一个值。你所描述的情况两者都没有。
If struct is passed into a method, unless it's passed by ref, it will not be changed by the method it's passed into. So in that sense, yes.
Can you create a parameter whose value can't be assigned within the method or whose properties cannot be set while within the method? No. You cannot prevent the value from being assigned within the method, but you can prevent it's properties from being set by creating an immutable type.
The question isn't whether the parameter or it's properties can be assigned to within the method. The question is what it will be when the method exits.
The only time any outside data is going to be altered is if you pass a class in and change one of it's properties, or if you pass a value by using the ref keyword. The situation you've outlined does neither.
建议(好吧,我)是使用一个为成员提供只读访问权限的界面。请记住,如果“真实”成员是引用类型,则仅提供对支持该类型的读取操作的接口的访问——递归到整个对象层次结构。
The recommended (well, by me) is to use an interface that provides read only access to the members. Remembering that if the "real" member is a reference type, then only provide access to an interface supporting read operations for that type -- recursing down the entire object hierarchy.