views:

542

answers:

5

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.
}
A: 

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.

David Morton
I would +1 except for the comment about immutability...having an immutable type wouldn't accomplish what he's looking for.
Adam Robinson
Sure it would, by default. An immutable type, not passed by reference, will ensure that the value, outside the method, doesn't change.
David Morton
True, but his example is about changing the value *inside* the method. In his example code, x is an Int32, which is immutable, but he's still allowed to write `x++`. That is, he's trying to prevent reassignment of the parameter, which is orthogonal to mutability of the parameter's value.
itowlson
I just re-read my post. My wording is confusing. I took that line out completely.
David Morton
I downvoted you for misunderstanding the question; it's not about changing the value AFTER the call, but changing it WITHIN it.
Noon Silk
@silky Kinda strange to downvote three answers that misunderstood the same question. Perhaps it's not the reader's fault the question was misunderstood. You know, when a man divorces his third wife, it's typically not the wives' fault.
David Morton
@David: It's the purpose of the voting system. To order by relevance. I don't see why it should concern you to be corrected.
Noon Silk
@David @silky I think Rosarch gave a bad example case, because integers are pass by value, and with that the original intention of the question became a little opaque. Hence my original comment about the Java final keyword.
Corey Sunwold
@Corey I found it trivial to follow, but that's because I've got a background in Java. I don't see why anyone should be upset about being wrong. It just shows that the question needs to be read carefully, and that you shouldn't be so fast to answer. But nevertheless, I don't think David will accept my comments. It's fairly meaningless to me, though, as I was simply providing a reason for the downvote, and trying to follow the rules of the (IMHO, significantly wrong) voting system.
Noon Silk
+1  A: 

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.

Joel Coehoorn
I downvoted you for misunderstanding the question; it's not about changing the value AFTER the call, but changing it WITHIN it.
Noon Silk
@silky - I didn't misunderstand the question. I'm talking about within the function as well. I'm saying it's a weird restriction to send to a function, because it doesn't really stop anything. If someone forgets the original parameter changed they're just as likely to forget a copy changed.
Joel Coehoorn
@Joel I disagree. Merely providing a comment explaining the downvote.
Noon Silk
+1 because you understood the OPs misunderstanding.
erikkallen
+8  A: 

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.

"NOTE: The Java language also supports having final parameters to a method. This functionality is non-existent in C#."

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

Corey Sunwold
"Unfortunately"? How would that differ from the current capability?
John Saunders
@John Saunders Unfortunate because Rosarch is looking for a feature that doesnt exist.
Corey Sunwold
@Corey: he's looking for a feature with no effect. In his example, the parameter would be constant without the `const`.
John Saunders
@John: It's not constant within the method. That's the issue.
Noon Silk
Its only constant outside the scope of this method. Ignoring whether it was passed by reference or by value, Rosarch doesn't want the parameter to change within the scope of the method. Thats the key difference.
Corey Sunwold
@silky: reading his post, that's not what he's asking for. He's asking to ensure the method doesn't change the actual parameters.
John Saunders
+2  A: 

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:

Hans Passant
Note that you don't need a naming convention to enforce this; you could always do it use an analysis tool after the fact (not great, but nevertheless). I believe Gendarme (http://www.mono-project.com/Gendarme) has a rule for it, and probably StyleCop/FxCop too.
Noon Silk
+1  A: 

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 :-)

Ben