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.
Related
I wish to encode hard coded value of a const Point struct.
Why does the compiler not allow neither internal, nor arbitrary structs to be replaced during compilation? Since the internal bitwise representation can be established at compile time (in both cases), there is no apparent reason for the restriction.
My question is: Is there a way to hard-code a predefined set of bytes in c# that can be interpreted at compile time as the appropriate type, since all structs have a predetermined memory outline.
EDIT:
To clarify: Compile time means C# -> IL byte-code as stored in the output assembly.
The use case example:
public void Draw(Bitmap bmp, Point Location = new Point(0,0)) // invalid
This is an error because the new Point(0,0) cannot be evaluated at compile time. I can pass in int X = 0, int Y = 0 or the nullable Point? Location = null and generate the struct inside of the method, or Overload the method without the optional parameters and call the main method passing in the default values, but that technique incurs a performance penalty in terms of the extra method calls required.
This may not be appropriate for all structs, since the constructor could rely on, or change, external state or randomness.
FINAL EDIT:
This is now possible. Making the question moot. Yay.
The issue was the incorrect belief that the new keyword always implied heap allocation or dynamic stack allocation, with constant arguments neither case was true.
Why does the compiler not allow neither internal, nor arbitrary structs to be replaced during compilation? Since the internal bitwise representation can be established at compile time (in both cases), there is no apparent reason for the restriction.
All not-implemented features are not implemented for the same reason. To be implemented, a feature must be thought of, judged to be appropriate, designed, specified, implemented, tested, documented and shipped. All those things must happen. For your proposed feature, none of them happened. Therefore, no feature.
Programming language designers are not required to provide a justification for why a feature was not implemented. Rather, the people who want the feature are required to provide a reason why programming language designers should spend their valuable time implementing a feature that you want.
The C# design process is open, and the compiler source code is available. Why have you not designed and implemented the feature? If it is fair for you to ask the designers that question, it's fair for them to ask it of you! You're a computer programmer; get busy programming computers and build the feature if you think it is worthwhile, and then convince the language team to accept your pull request. If you don't think it is worth your time to do that, well, probably the language designers feel the same way.
My question is: Is there a way to hard-code a predefined set of bytes in c# that can be interpreted at compile time as the appropriate type, since all structs have a predetermined memory outline.
I'm not sure what you mean by "at compile time"; can you clarify?
There are ways to store byte arrays in an assembly, sure. Make a C# program with a byte array initialized to all constant values and ildasm the assembly; you'll see the code that the C# compiler generates to get the byte array image out of the metadata and into the array.
You could implement similar shenanigans to get a byte array, fix the array in place, and then use unsafe pointer magic to reinterpret the array bytes as struct bytes. That sounds extraordinarily dangerous, and might mess up the performance of the garbage collector. I would not wish to do so myself, but you seem pretty keen on this feature, so go for it and report back what you find out!
Alternatively, C++/CLI probably implements the feature you want; I've never used it but that seems like the sort of thing it would do. You could write a little program in C++/CLI that does what you want, and then either (1) use that program's assembly as a dependency of your assembly, (2) compile it as a netmodule link it in to your assembly via the usual netmodule linking gear (yuck) or (3) deduce how they implemented the feature and then do the same.
You can convert a struct into byte array and encode a byte array. It may work like this: (please compile and fix any errors (typing through mobile))
Suppose your struct is:
public struct TestStruct
{
public int x;
public string y;
}
public byte[] GetTestByte(TestStruct c)
{
var intGuy = BitConverter.GetBytes(c.x);
var stringGuy = Encoding.UTF8.GetBytes(c.y);
var both = stringGuy.Concat(intGuy).Concat(new byte[1]).ToArray();
return both;
}
Now you can encode a byte array like:
Convert.ToBase64String(byteArray);
There is no direct way to encode a struct. Its a value type at best and probably there as legacy for C and 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
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.
Can anyone tell what is the point of a constant in C#?
For example, what is the advantage of doing
const int months = 12;
as opposed to
int months = 12;
I get that constants can't be changed, but then why not just... not change it's value after you initialize it?
If the compiler knows that a value is constant and will never change, it can compile the value directly into your program.
If you declare pi to be a constant, then every time it sees pi / 2 the compiler can do the computation and insert 1.57... directly into the compiled code. If you declare pi as a variable, then every time your program uses pi / 2 the computer will have to reference the pi variable and multiply it by 0.5, which is obviously slower.
I should also add that C# has readonly which is for values that the compiler cannot compute, but which cannot change for the duration of your program's execution. For example, if you wanted a constant ProgramStartTime, you would have to declare it readonly DateTime ProgramStartTime = DateTime.Now because it has to be evaluated when the program starts.
Finally, you can create a read-only property by giving it a getter but no setter, like this:
int Months { get { return 12; } } but being a property it doesn't have to have the same value every time you read it, like this:
int DaysInFebruary { get { return IsLeapYear ? 29 : 28 } }
The difference between "can't change" and "won't change" only really becomes apparent when one of the following situations obtains:
other developers begin working on your code,
third-parties begin using your code, or
a year passes and you return to that code.
Very similar questions arise when talking about data accessibility. The idea is that you want your code to provide only as much flexibility as you intend, because otherwise someone (possibly you) will come along and do something you did not intend, which leads to bugs!
If you never make mistakes, nobody on any team you work with ever makes mistakes, you never forget the exact purpose of a variable you've defined even after coming back to code you haven't looked at in months or years, and you and everyone you work with 100% reliably recognizes, understands and follows your intention of never changing a const value when you haven't bothered to use a built-in language construct that both clearly indicates and enforces constness, then no, there's no point.
If any one of those things ever turns out not to be the case, that's the point.
As for me, I find that even when I'm at my most lucid, remembering more than seven things at once is pretty close to impossible, so I'll take all the help I can get to prevent mistakes, especially when the cost is a single keyword. If you're smarter than me, and you never have to work on a team with someone less smart than you, then do whatever you want.
In some cases, there may be some compiler optimizations that can be done based on constness (constant folding, for one, which collapses expressions consisting of constants at compile-time). But usually, that's not the point.
Keep in mind you may not be the only person using the value. Not only can't you change it, but nobody using your code (as a library, for example) can change it.
And marking it as constant also makes your intent clear.
That's it. The you tell the compiler it can never change, and the compiler can optimise much better knowing that it is immutable.
Using constants programmers have the advantage of Readability over actual Value like
const double PI = 3.14159;
It also speeds up computation compared to variables by inserting values at compile time and not being inferred from a register/memory location.
For several reasons:
You want to differentiate certain values that have certain meaning from other variables.
You may later forget you are not meant to change a value, and cause unforeseen behavior.
Your code may be used by other people an they may change it (especially if you're developing a library or an API).
Because every thing that can go wrong usually will - so prevent it by making such errors discoverable at compile time rather than runtime.
Declaring a value 'const' brings the compiler into play to help you enforce personal discipline, by not allowing any changes to that value.
Also, it will catch unexpected errors due to side-effects of passing a value (that you intend to treat as a constant) into a method that takes a 'ref' parameter and could conceivably alter the value unexpectedly.
Strictly speaking, "const" isn't necessary. Python, for example, has neither "const" nor "private"; you specify your intent with the naming convention of THIS_IS_A_CONSTANT and _this_is_private.
C#, however, has a design philosophy of catching errors at compile time rather than runtime.
All about readability, different semantics for programmer is true and you should know all of it.
But constants in C# (rather in .net) has very different semantics (in terms of implementation) as compared with ordinary variables.
Because a constant value never changes, constants are always considered to be part of the
defining type. In other words, constants are always considered to be static members, not
instance members. Defining a constant causes the creation of metadata. When code refers to a constant symbol, compilers embed the value in the emitted Intermediate Language (IL) code.
These constraints mean that constants don’t have a good cross-assembly versioning story, so you should use them only when you know that the value of a symbol will never change.
The "point" is so that you can use a single program-wide variable and have only one spot to change it.
Imagine if you were making a video game that relied on knowing the FPS (frames per second) in 100 different code files. So pretend the FPS was 50... and you had the number "50" in all those files and functions... then you realize that you wanted to make it 60 FPS... instead of changing those 100 files, you would just change this:
const int FRAMES_PER_SECOND = 60;
and in those files / functions, you would use the FRAMES_PER_SECOND variable.
By the way, this has nothing to do with C#... constants are in tons of languages.
It is a case of being explicit of your intention.
If you intend to change value, then do not use 'const'.
If you do not intend to change value, then use 'const'.
That way both compiler and third party (or yourself if you read your code after long time) can know what you intended. If you or somebody makes a mistake of changing value, then compiler can detect it.
And anyways, to use 'const' is not mandatory. If you think, you can handle 'constancy' yourself (without wanting compiler to detect mistake), then do not use 'const' ;-).
You should define a variable as "const" when you know the value of this will remain constant through out your application. So once you define a const, it value must be determinable at compile time and this value will be saved into the assembly's metadata. Some more important points abt Const:
A const can be defined only for types your compiler treats as primary types.
Constants are always considered to be the part of defining type.
They are always considered to be Static members.
Constants value are always embedded directly into the code, so constants dont require any memory to be allocated to them at run time.
Because of this embedding of the value into metadata, when somebody change the value of the const (in the assembly where the const is defined) due to versioning or some other requirement
then the user of the dll has to recompile his own assembly. And this issue can be avoided using "readonly" keyword.
One of the rule that many programmers follow is: Never hard-code any variables / except 0.
that means, instead of doing
for(int i=0; i<100; i++) {}
should do
const loopCount = 100;
....
for (int i=0; i<loopCount; i++) {}
I think using const is a good reason to replace this. And indeed, there's much more reason to this:
Optimize for compiler - memory, performance.
Tell the programmer that follow your work, this is CONSTANT
If you need to refactor, change your mind in the number, you know where to go. And make sure no other places in the code would change this.
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.