Const methods in C# - c#

In C++, you can define a constant method like so:
int func_that_does_not_modify_this(int arg) const {}
Placing const at the end of the function prevents you from accidentally modifying any of the internal properties, and lets the caller know that this function won't modify the object.
Is there a concept like this in C#?

No, there's nothing like that in C#. It's been talked about a lot, but it's quite difficult to make const work in such a way that it's verifiable at compile time, can't be cast away like it can in C++, and is still reasonably easy to actually use without everyone having to get it perfectly right when they design their own classes.
Of course, if you design your own types to be immutable (like string) then all instance methods on it are effectively const. This isn't always practical, but it's an important technique to use where appropriate.

Code Contract should provide such a feature in the future. Currently, you can mark a method as [Pure], which means it doesn't have any side-effects (i.e. doesn't modify any of the class members). Unfortunately, the current version of the tools does not enforce this rule, so using that attribute is for documentation purpose only. I'm pretty sure that in future version, it will be enforced via static-analysis (i.e. at compile-time), or at least that's what the documentation hints at.
Related SO questions: Pure functions in C#

No. There's nothing similar in C#.
No const & either.
As Jon points out you can obviously implement a const method, but there's no way beyond documentation to let the caller know that a method is const.

C# 8.0 adds support for C++ style const methods, but only to structs. You can add a readonly modifier to a method deceleration to make any modifications to state within it a compiler warning (which you can define as an error if you wish). A readonly struct method may still call a non-readonly method, but that method will be called on a copy of the struct to prevent any changes to the original data.
For more information:
📄 What's new in C# 8.0 | Readonly members
📄 Structure types (C# reference) | readonly instance members
▶️ What's new in C# 8 - Part 2 | Read Only Members

Related

C# Method-reference of constructor

In C# I can have references of methods and static methods. Can I also get the reference of a classes constructor?
In Java I can say Supplier<MyClass> createMyClass = MyClass::new (instead of the longer lambda syntax).
In C# I only know the notation Func<MyClass> createMyClass = () => MyClass(). But I think the Java way with the constructor reference is better readable.
And I don't want to make a static CreateMyClass function. I really want the constructor.
No, there's no equivalent of method group conversions for constructors, or properties, indexers or operators.
It's an entirely reasonable idea, but it isn't in C# at the moment. It is, however, tracked as part of a feature request in the C# design repo - so you may want to subscribe to that issue.

Is there reason why you can't declare a static variable within a C# method?

I've been working in C for the past couple of years and I've managed to get use to putting single-purpose, static variables near where they are used within my code.
While writing a very basic method that was in need of a method-scope static value, I was a bit surprised to find that the compiler didn't like that I tried to define a static object from within my method.
Googling has verified that this isn't possible within C#. Still, I'm curious why code, like the following, is completely off limits.
public int incrementCounterAndReturn()
{
static int i = 0;
return ++i;
}
Granted, this is a simplistic example that could be redefined for the same affect but that's beside the point. Method-scope, static values have their place and purpose. What design decisions have prevented such an implementation of static objects within C#?
We're on C# version 5.0 and it's 2013. I can only assume this isn't possible because of a design choice and not just because "that's complex and hard stuff to implement." Does anyone have any insider information?
The language design team is not required to provide a reason to not implement a feature. Rather, the person who wants the feature is required to make the case that the feature is the best possible way the design, implementation, test, and education teams can be spending their budgets. No one has ever successfully done so for your proposed feature.
Were I still on the design team and had this feature pitched I would point out that it is completely unnecessary. The feature in C is a known cause of developer confusion, particularly for novices, and the benefit of local vs type scope is tiny.
The underlying runtime does not provide method level static variables. In the CLR, all "static" data is defined on the type level, not method level. C# decided to not add this at the language level in its language design.
This is purely a design choice. VB.Net, which compiles to the same IL, does allow this via the Shared keyword in a Function or Sub statement (though it's handled via the compiler "promoting" the variable to a class level static variable).
Because in the CLR, static variables are associated with the TYPE. Storage for them is tied to the Type (class or stuct) they are associated with.
static variables are scoped to the class, not to an object instance. To make this work, your method must be declared static, and I believe your class must also be static (since instantiation is not relevant).
But the variable itself must be declared at the class level. C# doesn't allow you to create method-local static variables.
Worth noting: these kinds of maneuvers make it very difficult to unit test the method properly. Normally in C# one would make an ordinary class to hold such state; in fact, that's exactly how yield return works behind the scenes.
The .NET framework and languages were designed around the concept that anyone who is going to be compiling an assembly should be considered trustworthy enough to have access to all the code therein. From a semantic point of view, declaring a static variable foo within method bar would be equivalent to declaring a private static variable outside the method and accessing it within the method, provided only that one chooses as a name something which isn't used anywhere else. If one by convention combines the method name and meaning (e.g. bar_foo) one can generally avoid naming collisions pretty easily. Since the semantics are equivalent to having the variable declared outside the method, there's no need to have it declared inside.

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)
{}
....
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.
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:
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.
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.
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.
I believe there are two reasons C# is not const-correct.
The first is understandibility. Few C++ programmers understand const-correctness. The simple example of const int arg is cute, but I've also seen char * const * const arg - a constant pointer to constant pointers to non-constant characters. Const-correctness on pointers to functions is a whole new level of obfuscation.
The second is because class arguments are references passed by value. This means there's already two levels of constness to deal with, without an obviously clear syntax. A similar stumbling point is collections (and collections of collections, etc).
Const-correctness is an important part of the C++ type system. It could - in theory - be added to C# as something that is only checked at compile-time (it doesn't need to be added to the CLR, and wouldn't affect the BCL unless the notion of const member methods were included).
However, I believe this is unlikely: the second reason (syntax) would be quite difficult to solve, which would make the first reason (understandibility) even more of a problem.
This is possible since C# 7.2 (December 2017 with Visual Studio 2017 15.5).
For Structs and basic types only!, not for members of classes.
You must use in to send the argument as an input by reference. See:
See:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/in-parameter-modifier
For your example:
....
static void TestMethod1(in MyStruct val)
{
val = new MyStruct; // Error CS8331 Cannot assign to variable 'in MyStruct' because it is a readonly variable
val.member = 0; // Error CS8332 Cannot assign to a member of variable 'MyStruct' because it is a readonly variable
}
....
static void TestMethod2(in int val)
{
val = 0; // Error CS8331 Cannot assign to variable 'in int' because it is a readonly variable
}
....
const means "compile-time constant" in C#, not "readonly but possibly mutable by other code" as in C++. A rough analog of C++ const in C# is readonly, but that one is only applicable to fields. Aside from that, there is no C++-like notion of const correctness in C# at all.
The rationale is hard to tell for sure, because there are a lot of potential reasons, but my guess would be desire to keep the language simple first and foremost, and uncertain advantages of implementing this second.

Using consts in static classes

I was plugging away on an open source project this past weekend when I ran into a bit of code that confused me to look up the usage in the C# specification.
The code in questions is as follows:
internal static class SomeStaticClass
{
private const int CommonlyUsedValue = 42;
internal static string UseCommonlyUsedValue(...)
{
// some code
value = CommonlyUsedValue + ...;
return value.ToString();
}
}
I was caught off guard because this appears to be a non static field being used by a static function which some how compiled just fine in a static class!
The specification states (§10.4):
A constant-declaration may include a
set of attributes (§17), a new
modifier (§10.3.4), and a valid
combination of the four access
modifiers (§10.3.5). The attributes
and modifiers apply to all of the
members declared by the
constant-declaration. Even though
constants are considered static
members, a constant-declaration
neither requires nor allows a static
modifier. It is an error for the same
modifier to appear multiple times in a
constant declaration.
So now it makes a little more sense because constants are considered static members, but the rest of the sentence is a bit surprising to me. Why is it that a constant-declaration neither requires nor allows a static modifier? Admittedly I did not know the spec well enough for this to immediately make sense in the first place, but why was the decision made to not force constants to use the static modifier if they are considered static?
Looking at the last sentence in that paragraph, I cannot figure out if it is regarding the previous statement directly and there is some implicit static modifier on constants to begin with, or if it stands on its own as another rule for constants. Can anyone help me clear this up?
UPDATE: This question was the subject of my blog on June 10th, 2010. Thanks for the great question!
why was the decision made to not force constants to use the static modifier if they are considered static?
Suppose constants are considered to be static. There are three possible choices:
Make static optional: "const int x..." or "static const int x..." are both legal.
Make static required: "const int x..." is illegal, "static const int x..." is legal
Make static illegal: "const int x..." is legal, "static const int x..." is illegal.
Your question is why did we choose (3)?
The design notes from 1999 do not say; I just checked. But we can deduce what was probably going through the language designer's heads.
The problem with (1) is that you could read code that uses both "const int x..." and "static const int y..." and then you would naturally ask yourself "what's the difference?" Since the default for non-constant fields and methods is "instance" unless "static", the natural conclusion would be that some constants are per-instance and some are per-type, and that conclusion would be wrong. This is bad because it is misleading.
The problem with (2) is that first off, it is redundant. It's just more typing without adding clarity or expressiveness to the language. And second, I don't know about you, but I personally hate it when the compiler gives me the error "You forgot to say the magic word right here. I know you forgot to say the magic word, I am one hundred percent capable of figuring out that the magic word needs to go there, but I'm not going to let you get any work done until you say the magic word".
The problem with (3) is that the developer is required to know that const logically implies static. However, once the developer learns this fact, they've learned it. It's not like this is a complex idea that is hard to figure out.
The solution which presents the fewest problems and costs to the end user is (3).
It is interesting to compare and contrast this with other places in the language where different decisions were made.
For example, overloaded operators are required to be both public and static. In this case, again we are faced with three options:
make public static optional,
make it required, or
make it illegal.
For overloaded operators we chose (2). Since the natural state of a method is private/instance it seems bizarre and misleading to make something that looks like a method public/static invisibly, as (1) and (3) both require.
For another example, a virtual method with the same signature as a virtual method in a base class is supposed to have either "new" or "override" on it. Again, three choices.
make it optional: you can say new, or override, or nothing at all, in which case we default to new.
make it required: you have to say new or override, or
make it illegal: you cannot say new at all, so if you don't say override then it is automatically new.
In this case we chose (1) because that works best for the brittle base class situation of someone adds a virtual method to a base class that you don't realize you are now overriding. This produces a warning, but not an error.
My point is that each of these situations has to be considered on a case-by-case basis. There's not much general guidance here.
Basically, const implies static already, since the value cannot be changed at runtime. There's no reason for you to ever declare static const, since it's already implied, and the language designers decided to make the language syntax reflect that.
The specification language is basically saying "Const is always static, so you can't explicitly say static and const since it's redundant."
It isn't required or allowed because it's redundant. If all const members are static, then only confusion can arise from allowing some of them to be specified as static and some of them not to be.
Another reason to disallow declare constants as static is that from CLR point of view the constants are not not stored in memory along with other static fields of the type.
The constants don't have memory address and you cannot get reference to the constant value (the only exception is string constants). At runtime the type holding constant definition won't be loaded if other static/nonstatic members are not referenced. If it is the only type in the assembly, you can even safely delete it's DLL from the disk after compilation.
So, the constants are 'static' only in terms of 'may be referenced from static methods'. Constants do not have any other 'static' properties as other static type members do.

Why does C# not allow const and static on the same line?

Why does C# not allow const and static on the same line? In Java, you must declare a field as 'static' and 'final' to act as a constant. Why does C# not let you declare const's as final?
I make the further distinction that in Java, every interface is public and abstract, whether this is explicitly declared or not. Aren't const's effectively static in nature? WHy does C# balk at this?
const and static really do mean different things, different storage mechanism, different initialisation. static is read/write, therefore must have memory allocated for storage and must be initialised at runtime. A static can be initialised with a literal value or an expression. In contrast, a const is immutable and must be initialised with a compile time constant (typically a literal value, or an expression that can be fully evaluated at compile time). The value is known at compile time so it can be embedded directly in the generated code, therefore requires no storage to be allocated at runtime.
Constants by their nature are static, so that would be redundant.
As said before, static final in Java is the same as static readonly in C#. In fact, you are saying that this member is static and its content can't be changed. Also you can specify in both cases the value from static constructor.
But const in C# is completely different thing. It's more along the lines of constants in C (DEFINE directives) but with OOP in mind. It's static because it's constant - every instance would have this constant with the same value, no constructor can set it. Also it's possible that someone would like to access the constant without having to create an instance. When you think about it non-static constant just doesn't make sense. You can almost say that constants are not part of an object - they just use it to provide context, a strong name.
Java doesn't have an equivalent to const. You can read somewhere that static final is equivalent to DEFINE but that's just so vague. Completely different mechanism, nothing in common but in the end result in the code is the same - better maintainability and readability of the code.
You just have to stop thinking about constants in C# as static members because they are not. Think of them as OOP version of DEFINE. When you consider encapsulation only reason for final and readonly fields is to prevent your own code from accidently changing its value. And that doesn't sound like constant to me.
Sumary:
final = readonly
static final = static readonly
N/A = const
It is true that a C# const implies static BUT, C# has an equivalent to Java's final keyword in the keyword readonly.
So, in fact, C# allows a const final, it is static readonly in C#.
Because allowing and not requiring modifiers that are inherent can cause confusion. If you see
static const int A = 3
const int B = 5
you may believe that they are 2 different kinds of constants.
Even VB 2008 (which can be very verbose if you wish) doesn't allow that.

Categories

Resources