Can the parameters be constant?

I am looking for the C # equivalent for Java final . He exists?

Does C # have something like the following:

 public Foo(final int bar); 

In the above example, bar is a read-only variable and cannot be changed to Foo() . Is there any way to do this in C #?

For example, maybe I have a long method that will work with the x , y and z coordinates for some object (ints). I want to be absolutely sure that the function does not change these values โ€‹โ€‹in any way, thereby distorting the data. So I would like to declare them read-only.

 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. } 
+78
parameter-passing c # const readonly
Feb 26 '10 at 2:13
source share
9 answers

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 in fields.

NOTE. The Java language also supports the presence of final method parameters. This functionality is missing in C #.

from http://www.25hoursaday.com/CsharpVsJava.html

UPDATE (2019/08/13): I will add this for clarity, as it is accepted and takes first place in the list. Now it is possible with in parameters. See the answer below for details.

+59
Feb 26 2018-10-02T00
source share

Now it is possible in C # version 7.2:

You can use the in keyword in a method signature. MSDN documentation .

The in keyword should be added before specifying a method argument.

Example, valid method in C # 7.2:

 public long Add(in long x, in long y) { return x + y; } 

The following is currently prohibited:

 public long Add(in long x, in long y) { x = 10; // It is not allowed to modify an in-argument. return x + y; } 

The following error will appear when trying to change x or y , since they are marked in :

Cannot assign to 'in long' variable because it is a read-only variable

Marking an argument with in means:

This method does not change the value of the argument used as this parameter.

+23
Jan 2 '18 at 21:30
source share

I will start with the int part. int is the type of value, and in .Net means that you are really dealing with a copy. This is a really strange constructive restriction to say the method "You may have a copy of this value. This is your copy, not mine, I will not see it again, but you cannot change the copy." The method call implies that copying this value is OK, otherwise we could not safely call this method. If the method requires the original, leave it to the developer to make a copy to save it. Either give the method a value, or do not give the method a value. Do not go between them.

Go to reference types. Now this is a bit confusing. Do you mean a permalink where the link itself cannot be changed, or a completely locked immutable object? If the first, links in .Net are by default passed by value. That is, you get a copy of the certificate. Thus, we have essentially the same situation as for value types. If a developer needs a source link, they can save it themselves.

It just leaves us with a permanent (locked / unchanged) object. This may sound good in terms of runtime, but how should the compiler use it? Because properties and methods can have side effects, you should essentially be limited to read-only access. Such an object is unlikely to be very interesting.

+8
Feb 26 '10 at 2:23
source share

Answer: C # does not have a const function, such as C ++.

I agree with Bennett Dill.

The const keyword is very useful. In the example, you used int, and people donโ€™t understand your point. But why, if the parameter is a user of a huge and complex object that cannot be changed inside this function? That the use of the const keyword: parameter cannot be changed inside this method, because [any reason here] does not matter for this method. The const keyword is very powerful, and I really miss it in C #.

+8
Dec 20 '11 at 18:09
source share

Here is a short and sweet answer that is likely to get a lot of votes. I have not read all posts and comments, so please forgive me if this was previously suggested.

Why not take your parameters and pass them to an object that exposes them as immutable, and then use that object in your method?

I understand that this is probably a very obvious work that has already been considered, and the OP is trying to avoid this by asking this question, but I felt that it should be here no less ...

Good luck :-)

+7
Feb 26 '10 at 4:05
source share

Create an interface for your class that has readonly access objects only. Then let your parameter have this interface, not the class itself. Example:

 public interface IExample { int ReadonlyValue { get; } } public class Example : IExample { public int Value { get; set; } public int ReadonlyValue { get { return this.Value; } } } public void Foo(IExample example) { // Now only has access to the get accessors for the properties } 

For structures, create a common const shell.

 public struct Const<T> { public T Value { get; private set; } public Const(T value) { this.Value = value; } } public Foo(Const<float> X, Const<float> Y, Const<float> Z) { // Can only read these values } 

However, it is worth noting that it is strange that you want to do what you ask to do with respect to structures, as a writer of a method that you should know about what happens in this method. This will not affect the values โ€‹โ€‹passed to change them in the method, so your only concern is to make sure that you behave in the method you are writing. There comes a time when vigilance and clean code are the key, over the execution of const and other such rules.

+5
Aug 24 '13 at 17:05
source share

If you often encounter similar problems, then you should consider "Hungarian applications." Good looking, unlike bad looking . Although this usually does not try to express the constancy of the method parameter (which is too unusual), of course, nothing prevents you from adding an extra "c" before the identifier name.

To all those who want to press the button down now, read the opinion of these luminaries on the topic:

+3
Feb 26 2018-10-12T00
source share

I know it might be a little late. But for people who are still looking for other ways to do this, there may be another way to limit this C # standard. We could write a wrapper class called ReadOnly <T>, where T: struct. When implicitly converted to the base type T. But only an explicit conversion to the wrapper <T> class. Which will ensure that compiler errors are executed if the developer tries an implicit set of values โ€‹โ€‹of type ReadOnly <T>. As I will demonstrate two possible use cases below.

USAGE 1 required caller definition to change. This use will only be used to verify that the TestCalled function code is correct. Although at the release / assembly level you should not use it. Because on a large scale, math operations can overflow with conversions and make your code slow. I would not use it, but only for demonstration I published it.

USE 2, which I would suggest, has a Debug vs Release function demonstrated in the TestCalled2 function. There would also be no conversion to TestCaller functions using this approach, but this requires a bit more coding of TestCaller2 definitions using the compiler. You may notice compiler errors in the debug configuration, while when configuring all the code in the TestCalled2 function will compile successfully.

 using System; using System.Collections.Generic; public class ReadOnly<VT> where VT : struct { private VT value; public ReadOnly(VT value) { this.value = value; } public static implicit operator VT(ReadOnly<VT> rvalue) { return rvalue.value; } public static explicit operator ReadOnly<VT>(VT rvalue) { return new ReadOnly<VT>(rvalue); } } public static class TestFunctionArguments { static void TestCall() { long a = 0; // CALL USAGE 1. // explicite cast must exist in call to this function // and clearly states it will be readonly inside TestCalled function. TestCalled(a); // invalid call, we must explicit cast to ReadOnly<T> TestCalled((ReadOnly<long>)a); // explicit cast to ReadOnly<T> // CALL USAGE 2. // Debug vs Release call has no difference - no compiler errors TestCalled2(a); } // ARG USAGE 1. static void TestCalled(ReadOnly<long> a) { // invalid operations, compiler errors a = 10L; a += 2L; a -= 2L; a *= 2L; a /= 2L; a++; a--; // valid operations long l; l = a + 2; l = a - 2; l = a * 2; l = a / 2; l = a ^ 2; l = a | 2; l = a & 2; l = a << 2; l = a >> 2; l = ~a; } // ARG USAGE 2. #if DEBUG static void TestCalled2(long a2_writable) { ReadOnly<long> a = new ReadOnly<long>(a2_writable); #else static void TestCalled2(long a) { #endif // invalid operations // compiler will have errors in debug configuration // compiler will compile in release a = 10L; a += 2L; a -= 2L; a *= 2L; a /= 2L; a++; a--; // valid operations // compiler will compile in both, debug and release configurations long l; l = a + 2; l = a - 2; l = a * 2; l = a / 2; l = a ^ 2; l = a | 2; l = a & 2; l = a << 2; l = a >> 2; l = ~a; } } 
+2
Apr 30 '16 at 14:20
source share

If a struct is passed to the method, if it is not passed to ref, it will not be changed by the method to which it was passed. So in that sense, yes.

Can you create a parameter whose value cannot be assigned in the method or whose properties cannot be set within the method? No. You cannot prevent the assignment of a value in a method, but you can prevent it from setting properties by creating an immutable type.

The question is not whether a parameter or its properties can be assigned inside a method. The question is what will happen when the method comes out.

The only time that any external data is changed is to pass a class and change one of its properties or pass a value using the ref keyword. The situation you indicated does not.

0
Feb 26 '10 at 2:15
source share



All Articles