c# Const vs. Readonly, Scope, Usings
-
With C# getting to version 7+ I wish I could have some basic improvments. Is it me or do you get confused by this? Why can't I say
const DateTime today = DateTime.Now;
I can see readonly for parameters and such, but I would be happy using const there too
void Doit(const MyObj arg) ...
For properties, why can't I hide the worker variable for the rest of the class?
public int PageNbr
{
int _worker = 9;get { return _worker;}
set { _worker = value; }
}For destructors, why can't you give me option to destroy right away? I hate disposing with all its using code bloat. How about a free keyword on a variable or something to get me out of the business of resource management. If you open a file and a DB you have to nest usings before you even get started doing some work! Or maybe I'm missing something?
- Pete
-
With C# getting to version 7+ I wish I could have some basic improvments. Is it me or do you get confused by this? Why can't I say
const DateTime today = DateTime.Now;
I can see readonly for parameters and such, but I would be happy using const there too
void Doit(const MyObj arg) ...
For properties, why can't I hide the worker variable for the rest of the class?
public int PageNbr
{
int _worker = 9;get { return _worker;}
set { _worker = value; }
}For destructors, why can't you give me option to destroy right away? I hate disposing with all its using code bloat. How about a free keyword on a variable or something to get me out of the business of resource management. If you open a file and a DB you have to nest usings before you even get started doing some work! Or maybe I'm missing something?
- Pete
Using statements tell .Net to dispose resources/object instances (auto-magically). You nest your using statements so that once that statement block is done executing is is then released (auto-magically). Each nested statement block frees itself upon completion. Edit: Lot's of stuff on the internet about this. Objects have to implement IDisposable to be used in "using statements". I forgot to mention that these questions should be posted in the Q&A so that people can tell you search Google for the answers. Silly me. :-O
-
With C# getting to version 7+ I wish I could have some basic improvments. Is it me or do you get confused by this? Why can't I say
const DateTime today = DateTime.Now;
I can see readonly for parameters and such, but I would be happy using const there too
void Doit(const MyObj arg) ...
For properties, why can't I hide the worker variable for the rest of the class?
public int PageNbr
{
int _worker = 9;get { return _worker;}
set { _worker = value; }
}For destructors, why can't you give me option to destroy right away? I hate disposing with all its using code bloat. How about a free keyword on a variable or something to get me out of the business of resource management. If you open a file and a DB you have to nest usings before you even get started doing some work! Or maybe I'm missing something?
- Pete
pherschel wrote:
const DateTime today = DateTime.Now;
What happens if you're still using your application after midnight?
pherschel wrote:
For properties, why can't I hide the worker variable for the rest of the class? public int PageNbr { int _worker = 9; get { return _worker;} set { _worker = value; } }
Something doesn't look right with this, but assuming I correctly guessed what you're trying to do, you can initialize auto properties at declaration now and not have a backing variable at all.
public int PageNbr{ get; set; } = 9;
Did you ever see history portrayed as an old man with a wise brow and pulseless heart, waging all things in the balance of reason? Is not rather the genius of history like an eternal, imploring maiden, full of fire, with a burning heart and flaming soul, humanly warm and humanly beautiful? --Zachris Topelius Training a telescope on one’s own belly button will only reveal lint. You like that? You go right on staring at it. I prefer looking at galaxies. -- Sarah Hoyt
-
With C# getting to version 7+ I wish I could have some basic improvments. Is it me or do you get confused by this? Why can't I say
const DateTime today = DateTime.Now;
I can see readonly for parameters and such, but I would be happy using const there too
void Doit(const MyObj arg) ...
For properties, why can't I hide the worker variable for the rest of the class?
public int PageNbr
{
int _worker = 9;get { return _worker;}
set { _worker = value; }
}For destructors, why can't you give me option to destroy right away? I hate disposing with all its using code bloat. How about a free keyword on a variable or something to get me out of the business of resource management. If you open a file and a DB you have to nest usings before you even get started doing some work! Or maybe I'm missing something?
- Pete
Quote:
Why can't I say
const DateTime today = DateTime.Now;
Because DateTime.Now is not a compile-time constant, it's a run time property which returns an non-constant value. Suppose it did allow it: what value should be in
today
? The DatetIme when the app was started? When the assembly containing the code was loaded? When the class containing the constant value was statically initialized? What would happen if two different classes (or worse assemblies) both declared the same value? Would they be the same? Should they be? How would the system decide for you? That's the point ofconst
vsreadonly
- the former is a compile time constant value, the later is a runtime constant value. That way, you have the choice for what exactly you want to do, rather than letting the system try to make up it's mind for you.Bad command or file name. Bad, bad command! Sit! Stay! Staaaay... AntiTwitter: @DalekDave is now a follower!
-
With C# getting to version 7+ I wish I could have some basic improvments. Is it me or do you get confused by this? Why can't I say
const DateTime today = DateTime.Now;
I can see readonly for parameters and such, but I would be happy using const there too
void Doit(const MyObj arg) ...
For properties, why can't I hide the worker variable for the rest of the class?
public int PageNbr
{
int _worker = 9;get { return _worker;}
set { _worker = value; }
}For destructors, why can't you give me option to destroy right away? I hate disposing with all its using code bloat. How about a free keyword on a variable or something to get me out of the business of resource management. If you open a file and a DB you have to nest usings before you even get started doing some work! Or maybe I'm missing something?
- Pete
-
Using statements tell .Net to dispose resources/object instances (auto-magically). You nest your using statements so that once that statement block is done executing is is then released (auto-magically). Each nested statement block frees itself upon completion. Edit: Lot's of stuff on the internet about this. Objects have to implement IDisposable to be used in "using statements". I forgot to mention that these questions should be posted in the Q&A so that people can tell you search Google for the answers. Silly me. :-O
-
True enough. I'd love to banish usings somehow. I want to use a create & use an class, not manage it's lifetime.
- Pete
You don't have to use the "using statement". You can create an instance of the object and dispose of it manually when you are done.
-
With C# getting to version 7+ I wish I could have some basic improvments. Is it me or do you get confused by this? Why can't I say
const DateTime today = DateTime.Now;
I can see readonly for parameters and such, but I would be happy using const there too
void Doit(const MyObj arg) ...
For properties, why can't I hide the worker variable for the rest of the class?
public int PageNbr
{
int _worker = 9;get { return _worker;}
set { _worker = value; }
}For destructors, why can't you give me option to destroy right away? I hate disposing with all its using code bloat. How about a free keyword on a variable or something to get me out of the business of resource management. If you open a file and a DB you have to nest usings before you even get started doing some work! Or maybe I'm missing something?
- Pete
pherschel wrote:
Is it me or do you get confused by this? Why can't I say
const DateTime today = DateTime.Now;
Constants aren't variables, they just look like them, they are aids for the compiler, they don't exist at run-time. When you write
const int x = 5;
int y = 2;
int z = y + x;
bool b = z <= x;what gets compiled is this
int y = 2;
int z = y + 5;
bool b = z <= 5;The compiler replaces all instances of "x" with the constant value. If you could define x as DateTime.Now then what would be compiled? If it literally replaced "x" with "DateTime.Now" everywhere it appears then you almost certainly would not get the result you desire. If it replaced DateTime.Now with the date of compilation then that wouldn't work either. What you really want is a read-only variable, and that's why we have read only variables and constants. You have to understand what they are and use them appropriately, that's not a failing of .net. This is also why you can't make objects const.
const Person p = new Person();
p.FirstName = "John";
p.Age = 33;
Console.WriteLine (p); // what will the compiler replace "p" with?pherschel wrote:
For properties, why can't I hide the worker variable for the rest of the class?
Use the short-hand version
int PageNbr { get; set; }
Again it's simply a case of understanding the difference and knowing when and where to use the appropriate solution.
pherschel wrote:
For destructors, why can't you give me option to destroy right away?
Because .net is better at memory management than you are and if you leave .net to do your memory management you'll get code that performs well, if you try and do your own memory management you get code that performs badly. For one it means the code is harder for the compiler to optimise as the compiler likes to move your code around for the best overall result but when you have in-line memory management you lesser the optimiser's abilities. Also memory deallocation is expensive. If you could free your objects immediately you probably would (otherwise why would you want this feature?) and that will result in a not-insignificant performance hit. By leaving this aspect to .net it can clear the memory down at a time better suited, like when your app i
-
With C# getting to version 7+ I wish I could have some basic improvments. Is it me or do you get confused by this? Why can't I say
const DateTime today = DateTime.Now;
I can see readonly for parameters and such, but I would be happy using const there too
void Doit(const MyObj arg) ...
For properties, why can't I hide the worker variable for the rest of the class?
public int PageNbr
{
int _worker = 9;get { return _worker;}
set { _worker = value; }
}For destructors, why can't you give me option to destroy right away? I hate disposing with all its using code bloat. How about a free keyword on a variable or something to get me out of the business of resource management. If you open a file and a DB you have to nest usings before you even get started doing some work! Or maybe I'm missing something?
- Pete
pherschel wrote:
How about a free keyword on a variable or something to get me out of the business of resource management
Isn't that a contradiction in terms? Having done over a decade of C++ (and not missing it one bit), it seems to me that if you want a 'free' keyword, then you're not getting out of the business of resource management, you're asking to get into it... I must be completely misunderstanding something.
-
True enough. I'd love to banish usings somehow. I want to use a create & use an class, not manage it's lifetime.
- Pete
usings are only necessary when you need to know deterministically that a resource has been freed.
#SupportHeForShe Government can give you nothing but what it takes from somebody else. A government big enough to give you everything you want is big enough to take everything you've got, including your freedom.-Ezra Taft Benson You must accept 1 of 2 basic premises: Either we are alone in the universe or we are not alone. Either way, the implications are staggering!-Wernher von Braun
-
Quote:
Why can't I say
const DateTime today = DateTime.Now;
Because DateTime.Now is not a compile-time constant, it's a run time property which returns an non-constant value. Suppose it did allow it: what value should be in
today
? The DatetIme when the app was started? When the assembly containing the code was loaded? When the class containing the constant value was statically initialized? What would happen if two different classes (or worse assemblies) both declared the same value? Would they be the same? Should they be? How would the system decide for you? That's the point ofconst
vsreadonly
- the former is a compile time constant value, the later is a runtime constant value. That way, you have the choice for what exactly you want to do, rather than letting the system try to make up it's mind for you.Bad command or file name. Bad, bad command! Sit! Stay! Staaaay... AntiTwitter: @DalekDave is now a follower!
OriginalGriff wrote:
What would happen if two different classes (or worse assemblies) both declared the same value? Would they be the same? Should they be? How would the system decide for you?
Well no they because they would be separate instances (each class it's own), even if from the same or separate assemblies.
Sin tack the any key okay
-
Quote:
Why can't I say
const DateTime today = DateTime.Now;
Because DateTime.Now is not a compile-time constant, it's a run time property which returns an non-constant value. Suppose it did allow it: what value should be in
today
? The DatetIme when the app was started? When the assembly containing the code was loaded? When the class containing the constant value was statically initialized? What would happen if two different classes (or worse assemblies) both declared the same value? Would they be the same? Should they be? How would the system decide for you? That's the point ofconst
vsreadonly
- the former is a compile time constant value, the later is a runtime constant value. That way, you have the choice for what exactly you want to do, rather than letting the system try to make up it's mind for you.Bad command or file name. Bad, bad command! Sit! Stay! Staaaay... AntiTwitter: @DalekDave is now a follower!
OriginalGriff wrote:
That's the point of
const
vsreadonly
- the former is a compile time constant value, the later is a runtime constant value.While this is true,
readonly
is used for objects (except for_string_
:rolleyes:) as a compiler hack because_const_
ant (i.e._readonly_
) objects are really pointers whose value varies at load time. The fact the compiler writers did it for string means they could have done it for any object. But, I'm not interested in the object's pointer, I'm interested in the object's_const_
ant value.#SupportHeForShe Government can give you nothing but what it takes from somebody else. A government big enough to give you everything you want is big enough to take everything you've got, including your freedom.-Ezra Taft Benson You must accept 1 of 2 basic premises: Either we are alone in the universe or we are not alone. Either way, the implications are staggering!-Wernher von Braun
-
pherschel wrote:
How about a free keyword on a variable or something to get me out of the business of resource management
Isn't that a contradiction in terms? Having done over a decade of C++ (and not missing it one bit), it seems to me that if you want a 'free' keyword, then you're not getting out of the business of resource management, you're asking to get into it... I must be completely misunderstanding something.
dandy72 wrote:
I must be completely misunderstanding something.
Or he is...
#SupportHeForShe Government can give you nothing but what it takes from somebody else. A government big enough to give you everything you want is big enough to take everything you've got, including your freedom.-Ezra Taft Benson You must accept 1 of 2 basic premises: Either we are alone in the universe or we are not alone. Either way, the implications are staggering!-Wernher von Braun
-
Quote:
Why can't I say
const DateTime today = DateTime.Now;
Because DateTime.Now is not a compile-time constant, it's a run time property which returns an non-constant value. Suppose it did allow it: what value should be in
today
? The DatetIme when the app was started? When the assembly containing the code was loaded? When the class containing the constant value was statically initialized? What would happen if two different classes (or worse assemblies) both declared the same value? Would they be the same? Should they be? How would the system decide for you? That's the point ofconst
vsreadonly
- the former is a compile time constant value, the later is a runtime constant value. That way, you have the choice for what exactly you want to do, rather than letting the system try to make up it's mind for you.Bad command or file name. Bad, bad command! Sit! Stay! Staaaay... AntiTwitter: @DalekDave is now a follower!
-
Of course, you would use
_readonly_
for that. I happen to agree with you that_const_
should be allowed in these cases. The_readonly_
verb is an admitted hack by the compiler writers. After all,_string_
is an object (i.e. non-primitive) and you can use_const_
with it.#SupportHeForShe Government can give you nothing but what it takes from somebody else. A government big enough to give you everything you want is big enough to take everything you've got, including your freedom.-Ezra Taft Benson You must accept 1 of 2 basic premises: Either we are alone in the universe or we are not alone. Either way, the implications are staggering!-Wernher von Braun
-
Using statements tell .Net to dispose resources/object instances (auto-magically). You nest your using statements so that once that statement block is done executing is is then released (auto-magically). Each nested statement block frees itself upon completion. Edit: Lot's of stuff on the internet about this. Objects have to implement IDisposable to be used in "using statements". I forgot to mention that these questions should be posted in the Q&A so that people can tell you search Google for the answers. Silly me. :-O
That's not entirely true. Look at streams. One would think this is correct.
using (var outerStream = new MemoryStream(someData))
{
using (var innerStream = new TextReader(outerStream))
{
// do something
}
}However, the proper way is this
var outerStream = new MemoryStream(someData);
using (var innerStream = new TextReader(outerStream)
{
// do something
}This is because the a stream will dispose of the underlying streams when you call Stream.Dispose(). I had code analysis bark at me all the time until I figured this one out.
if (Object.DividedByZero == true) { Universe.Implode(); } Meus ratio ex fortis machina. Simplicitatis de formae ac munus. -Foothill, 2016
-
That's not entirely true. Look at streams. One would think this is correct.
using (var outerStream = new MemoryStream(someData))
{
using (var innerStream = new TextReader(outerStream))
{
// do something
}
}However, the proper way is this
var outerStream = new MemoryStream(someData);
using (var innerStream = new TextReader(outerStream)
{
// do something
}This is because the a stream will dispose of the underlying streams when you call Stream.Dispose(). I had code analysis bark at me all the time until I figured this one out.
if (Object.DividedByZero == true) { Universe.Implode(); } Meus ratio ex fortis machina. Simplicitatis de formae ac munus. -Foothill, 2016
I was always under the impression that any IO stuff should be done in the "using" statement. Once the memory stream instance is not needed then it will be disposed, no need to kill it manually. Can you please show be some supporting evidence to support your later example, because I don't know that to be entirely true.
-
pherschel wrote:
Is it me or do you get confused by this? Why can't I say
const DateTime today = DateTime.Now;
Constants aren't variables, they just look like them, they are aids for the compiler, they don't exist at run-time. When you write
const int x = 5;
int y = 2;
int z = y + x;
bool b = z <= x;what gets compiled is this
int y = 2;
int z = y + 5;
bool b = z <= 5;The compiler replaces all instances of "x" with the constant value. If you could define x as DateTime.Now then what would be compiled? If it literally replaced "x" with "DateTime.Now" everywhere it appears then you almost certainly would not get the result you desire. If it replaced DateTime.Now with the date of compilation then that wouldn't work either. What you really want is a read-only variable, and that's why we have read only variables and constants. You have to understand what they are and use them appropriately, that's not a failing of .net. This is also why you can't make objects const.
const Person p = new Person();
p.FirstName = "John";
p.Age = 33;
Console.WriteLine (p); // what will the compiler replace "p" with?pherschel wrote:
For properties, why can't I hide the worker variable for the rest of the class?
Use the short-hand version
int PageNbr { get; set; }
Again it's simply a case of understanding the difference and knowing when and where to use the appropriate solution.
pherschel wrote:
For destructors, why can't you give me option to destroy right away?
Because .net is better at memory management than you are and if you leave .net to do your memory management you'll get code that performs well, if you try and do your own memory management you get code that performs badly. For one it means the code is harder for the compiler to optimise as the compiler likes to move your code around for the best overall result but when you have in-line memory management you lesser the optimiser's abilities. Also memory deallocation is expensive. If you could free your objects immediately you probably would (otherwise why would you want this feature?) and that will result in a not-insignificant performance hit. By leaving this aspect to .net it can clear the memory down at a time better suited, like when your app i
F-ES Sitecore wrote:
Because .net is better at memory management than you are and if you leave .net to do your memory management you'll get code that performs well, if you try and do your own memory management you get code that performs badly.
Well, you could jump outside of the CLR and allocate memory directly such as
unsafe
{
[DllImport(@"C:\Windows\System32\kernal32.dll")
public static extern void * HeapAlloc(void * procHeap, UInt32 dword, UInt32 size);
}Not saying that this is a good thing but it's possible and pretty much defeats the purpose of the CLR and GC. Not to mention memory management is one of the most challenging aspects of computer programing. If it weren't for .Net, my programs would most likely leak memory all over the place (my C and C++ KungFu is not strong).
if (Object.DividedByZero == true) { Universe.Implode(); } Meus ratio ex fortis machina. Simplicitatis de formae ac munus. -Foothill, 2016
-
I was always under the impression that any IO stuff should be done in the "using" statement. Once the memory stream instance is not needed then it will be disposed, no need to kill it manually. Can you please show be some supporting evidence to support your later example, because I don't know that to be entirely true.
That little path of discovery started when I started learning the Cryptography namespace. This little code snippet (copied directly from MSDN) was getting flagged with CA2202 during code analysis.
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream(cipherText))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}This really boggled me as this is Microsoft example code being flagged as incorrect so I began to dig. Turns out there is still a lively debate about this since the documentation is a little unclear in this area. Refactoring it to the following stopped the code analysis from flagging the code.
MemoryStream memStream = new MemoryStream(data);
CryptoStream decStream = new CryptoStream(memStream, decryptor, CryptoStreamMode.Read);using (StreamReader reader = new StreamReader(decStream))
{
decryptedValue = Encoding.UTF8.GetBytes(reader.ReadToEnd());
}Research into this led me to this one little line in this MSDN article: StreamReader Constructor.
The StreamReader object calls Dispose() on the provided Stream object when StreamReader.Dispose is called.
This reads that when you close certain classes of streams, they also close the streams that underlie them as well. TL;DR Not all IDisposable classes behave the same way, event in Microsoft code, and theusing
statement isn't always the correct way.if (Object.DividedByZero == true) { Universe.Implode(); } Meus ratio ex fortis machina. Simplicitatis de formae ac munus. -Foothill, 2016
-
That little path of discovery started when I started learning the Cryptography namespace. This little code snippet (copied directly from MSDN) was getting flagged with CA2202 during code analysis.
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream(cipherText))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}This really boggled me as this is Microsoft example code being flagged as incorrect so I began to dig. Turns out there is still a lively debate about this since the documentation is a little unclear in this area. Refactoring it to the following stopped the code analysis from flagging the code.
MemoryStream memStream = new MemoryStream(data);
CryptoStream decStream = new CryptoStream(memStream, decryptor, CryptoStreamMode.Read);using (StreamReader reader = new StreamReader(decStream))
{
decryptedValue = Encoding.UTF8.GetBytes(reader.ReadToEnd());
}Research into this led me to this one little line in this MSDN article: StreamReader Constructor.
The StreamReader object calls Dispose() on the provided Stream object when StreamReader.Dispose is called.
This reads that when you close certain classes of streams, they also close the streams that underlie them as well. TL;DR Not all IDisposable classes behave the same way, event in Microsoft code, and theusing
statement isn't always the correct way.if (Object.DividedByZero == true) { Universe.Implode(); } Meus ratio ex fortis machina. Simplicitatis de formae ac munus. -Foothill, 2016
Good to know. Thanks.