Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are const parameters not allowed in C#?

It looks strange especially for C++ developers. In C++ we used to mark a parameter as const in order to be sure that its state will not be changed in the method. There are also other C++ specific reasons, like passing const ref in order to pass by ref and be sure that state will not be changed. But why can't we mark as method parameters const in C#?

Why can't I declare my method like the following?

    ....     static void TestMethod1(const MyClass val)     {}     ....     static void TestMethod2(const int val)     {}     .... 
like image 563
Incognito Avatar asked Jul 16 '10 08:07

Incognito


People also ask

Is it possible to use a constant in a parameter?

It is not recommended to use const on function parameters passed by value, because const has no effect on the caller: even if the variable is changed in the function there will be no side effects outside the function.

What is the one benefit of declaring the parameter as const?

Answer: The const qualifier Forbids the code to modify the argument, so the programmer can rest assured that the source object will remain unchanged.

Is const useless?

Adding const to a value-type parameter in the function declaration is useless. The caller won't care whether the parameter is modified or not because the caller's data won't be affected in any way.

What is const parameter?

A constant parameter, declared by the keyword const , is a read-only parameter. This means that we can not modify the value of the constant parameter in the function body. Using the const keyword tells the compiler that the value of that parameter will not be changed inside the function.


2 Answers

In addition to the other good answers, I'll add yet another reason why to not put C-style constness into C#. You said:

we mark parameter as const in order to be sure that its state will not be changed in method.

If const actually did that, that would be great. Const doesn't do that. The const is a lie!

Const doesn't provide any guarantee that I can actually use. Suppose you have a method that takes a const thing. There are two code authors: the person writing the caller and the person writing the callee. The author of the callee has made the method take a const. What can the two authors assume is invariant about the object?

Nothing. The callee is free to cast away the const and mutate the object, so the caller has no guarantee that calling a method that takes a const actually will not mutate it. Similarly, the callee cannot assume that the contents of the object will not change throughout the action of the callee; the callee could call some mutating method on a non const alias of the const object, and now the so-called const object has changed.

C-style const provides no guarantee that the object will not change, and is therefore broken. Now, C already has a weak type system in which you can do a reinterpret cast of a double into an int if you really want to, so it should not be a surprise that it has a weak type system with respect to const as well. But C# was designed to have a good type system, a type system where when you say "this variable contains a string" that the variable actually contains a reference to a string (or null). We absolutely do not want to put a C-style "const" modifier into the type system because we don't want the type system to be a lie. We want the type system to be strong so that you can reason correctly about your code.

Const in C is a guideline; it basically means "you can trust me to not try to mutate this thing". That shouldn't be in the type system; the stuff in the type system should be a fact about the object that you can reason about, not a guideline to its usage.

Now, don't get me wrong; just because const in C is deeply broken doesn't mean that the whole concept is useless. What I would love to see is some actually correct and useful form of "const" annotation in C#, an annotation that both humans and compilers could use to help them understand the code, and that the runtime could use to do things like automatic paralellization and other advanced optimizations.

For example, imagine if you could "draw a box" around a hunk of code and say "I guarantee that this hunk of code performs no mutations to any field of this class" in a way that could be checked by the compiler. Or draw a box that says "this pure method mutates the internal state of the object but not in any way that is observable outside the box". Such an object could not be safely multi-threaded automatically but it could be automatically memoized. There are all kinds of interesting annotations we could put on code that would enable rich optimizations and deeper understanding. We can do way better than the weak C-style const annotation.

However, I emphasize that this is just speculation. We have no firm plans to put this sort of feature into any hypothetical future version of C#, if there even is one, which we have not announced one way or the other. It is something I would love to see, and something which the coming emphasis on multi-core computing might require, but none of this should be in any way construed to be a prediction or a guarantee of any particular feature or future direction for C#.

Now, if what you want is merely an annotation on the local variable that is a parameter that says "the value of this parameter doesn't change throughout the method", then, sure, that would be easily done. We could support "readonly" locals and parameters that would be initialized once, and a compile-time error to change in the method. The variable declared by the "using" statement is already such a local; we could add an optional annotation to all locals and parameters to make them act like "using" variables. It's never been a very high priority feature so it has never been implemented.

like image 113
Eric Lippert Avatar answered Oct 14 '22 22:10

Eric Lippert


One of the reasons why there's no const correctness in C# is because it doesn't exist at the runtime level. Remember that C# 1.0 did not have any feature unless it was part of the runtime.

And several reasons why the CLR does not have a notion of const correctness are for example:

  1. It complicates the runtime; besides, the JVM didn't have it either, and the CLR basically started as a project to create a JVM-like runtime, not a C++-like runtime.
  2. If there is const correctness at the runtime level, there should be const correctness in the BCL, otherwise the feature is pretty much pointless as far as the .NET Framework is concerned.
  3. But if the BCL requires const correctness, every language on top of the CLR should support const correctness (VB, JavaScript, Python, Ruby, F#, etc.) That's not going to happen.

Const correctness is pretty much a language feature only present in C++. So it pretty much boils down to the same argumentation as to why the CLR does not require checked exceptions (which is a Java language-only feature).

Also, I don't think you can introduce such a fundamental type system feature in a managed environment without breaking backward compatibility. So don't count on const correctness ever entering the C# world.

like image 40
Ruben Avatar answered Oct 14 '22 21:10

Ruben