|
Again me
On the other hand
public void OutExample_03(out int outValue)
{
DoAnythingBefore();
outValue = 0;
}
does also compile, so I really don't see the logic why try catch will be handled Special.
It is like it is
modified 19-Jan-21 21:04pm.
|
|
|
|
|
Because at Compile-Time the Compiler doesn't know if the Try-Cath COULD be succesful or not. It only recognized that there is a possibility for not-assigning the variable ...
|
|
|
|
|
Because, as already explained, the try block can terminate before the variable has its value assigned. In this case the catch part will be called and the method returns, but the value of outValue is indeterminate.
In the case above it is assumed (by the compiler) that one of two things will happen:
1. The method completes successfully, in which case outValue will have been correctly assigned.
2. An exception occurs, in which case the method will not complete, so the value of outValue does not matter.
|
|
|
|
|
Let me give you an example that might clarify it for you.
public void ThisIsaReallyStupidThingToDo(string input, out int value)
{
try
{
if (string.IsNullOrWhiteSpace(input))
{
throw new ArgumentNullException($"The value of {nameof(input)} must be set");
}
int.TryParse(input, out value);
}
catch (Exception ex)
{
}
} So, if you pass in an empty string, value will never be set because you bypass it completely and hit the exception handler. That's why you have to handle value outside the try/catch.
This space for rent
|
|
|
|
|
Thank you for your Feedback.
Yes all of this I'm aware. But it is not a real Explanation why
{
outParam= ..
} vs.
try
{
outParam= ...
}
will be handled different. I don't see a chance that in the sequence "try{ outParam= ..." something strange can happen.
Anyway it is more a philosophical thing not a real Problem.
Thanks again for your Feedback.
modified 19-Jan-21 21:04pm.
|
|
|
|
|
It is a real explanation. It's about consistent predictable behaviour. Because the code can cause inconsistent behaviour in the try block, all cases have to be handled consistently. Put it another way, what if the JITter was to reorganize the code inside the try block, you could end up with a situation where things blow up because you allowed an inconsistent behaviour.
This space for rent
|
|
|
|
|
I Need to think about it. Most probably I'm too much fixed to my thoughts at the Moment.
Thanks
Bruno
modified 19-Jan-21 21:04pm.
|
|
|
|
|
It is not treated different. The compiler does not check if the code-block is doing something usefull. You introduced it, so it probably has a use (take not of post-processing like some code-injecting frameworks).
It merely checks whether each block has a correct flow. What use would it serve to also see if your code-block does throw exceptions, simply to check whether the exception handler "might" fire? Would make compiling a lot slower, since it would be checking a lot.
Now what is the upside of this check? To not run into the warning?
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
I have created the following code
var filename = "wwwroot/Counter/Counter.txt";
var counterStream = new FileStream(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
var reader = new StreamReader(counterStream);
var visits = Convert.ToInt32(reader.ReadLine());
visits = visits + 1;
var writer = new StreamWriter(counterStream);
writer.Write(visits);
counterStream.Dispose(); As you will realise, it is a counter for a website I am building. I am OK down to the line.
visits = visits + 1 Visits does contain one more than is originally stored in Counter.txt. However, the last three lines are not writing anything back to the file. I was expecting it to write a new line in the file, although obviously I want it to replace the original finally. I am at a loss as to why it hasn't. Could someone point me in the right direction, please.
|
|
|
|
|
You need to position the file pointer to the appropriate place, either by reading all of the existing lines (and keeping only the last one), or by using Stream.Seek to reposition the file pointer back to the beginning before the Write.
Cheers,
Mick
------------------------------------------------
It doesn't matter how often or hard you fall on your arse, eventually you'll roll over and land on your feet.
|
|
|
|
|
Counter.txt only contains the one number, the number of visits the site has had. My code reads and updates it OK but the code after that doesn't write it back to replace the one that is there. That's all I want to do; replace the old with the new value.
|
|
|
|
|
xiecsuk wrote: That's all I want to do; replace the old with the new value
In which case you need to Seek the stream pointer back to the beginning of the file before the Write
Cheers,
Mick
------------------------------------------------
It doesn't matter how often or hard you fall on your arse, eventually you'll roll over and land on your feet.
|
|
|
|
|
I am not an expert on C# and the Wrox manual I have called C# 6 and .NET Core 1.0 doesn't describe Seek in the pages describing The StreamWriter Class.
If I try and code
writer.Seek(0); it tells me that 'StreamWriter' does not contain a definition for 'Seek'. I am therefore at a loss as to how to proceed.
|
|
|
|
|
Seek the Stream , not the StreamWriter .
Stream.Seek Method (Int64, SeekOrigin) (System.IO)[^]
const string filename = "wwwroot/Counter/Counter.txt";
using (var counterStream = new FileStream(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
{
int visits;
using (var reader = new StreamReader(counterStream))
{
string line = reader.ReadLine;
int.TryParse(line, out visits);
}
visits = visits + 1;
counterStream.Seek(0L, SeekOrigin.Begin);
using (var writer = new StreamWriter(counterStream))
{
writer.Write(visits);
}
}
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
I have replaced my code with your code exactly as in your message and I get the following error message:
An exception of type 'System.ObjectDisposedException' occurred in System.IO.FileSystem.dll but was not handled in user code
Additional information: Cannot access a closed file. This occurs on the line counterStream.Seek(0L, SeekOrigin.Begin); . Perhaps this is why my code is not updating the file. Somehow, it also thinks it's closed after the update of visits .
visits has been read and incremented correctly in your code.
|
|
|
|
|
Sorry - I forgot that closing the reader also closes the stream.
Try using a different StreamReader constructor:
using (var reader = new StreamReader(counterStream, System.Text.Encoding.UTF8, true, 4096, true))
The last parameter tells the StreamReader not to close the Stream .
Alternatively, remove the using block for the StreamReader :
var reader = new StreamReader(counterStream);
string line = reader.ReadLine;
int.TryParse(line, out visits);
...
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Everything is now working correctly. Thank you very much Richard. Without your help I wouldn't have got there.
I hate C#. Most of my career I have used Fortran, Microsoft Access and Visual Basic. I am just too old to learn these newfangled languages.
|
|
|
|
|
|
Please see my reply to the first reply to my question.
|
|
|
|
|
Have you read and realized what Midi_Mick has written to you ?
You have to do the following to get the saved Counter :
1.1. Open the File
1.2. Read your Value
1.3. Close the File
And you have to do the following to save the Counter :
2.1. Open the File
2.2. Write your Value
2.3. Close the File
|
|
|
|
|
The problem as I see it is that closing the file half way through the update opens it up for another visitor to start updating it before I have written the updated value from the first visit. This negates the point of having a counter.
|
|
|
|
|
So...not the most performant thing, but this should help avoid concurrency issues.
private static int _count;
private static readonly string _fileName = @"C:\my\file\path\and.name";
private static readonly Object _sync = new Object();
public static void Increment()
{
lock(_sync)
{
_count++;
File.WriteAllText(_fileName, _count.ToString());
}
}
void AppStartEvent()
{
lock(_sync)
{
var seed = File.ReadAllText(_fileName);
int result = 0;
if(int.TryParse(seed,out result))
{
_count = result;
}else{
_count = 0;
}
}
}
"There are three kinds of lies: lies, damned lies and statistics."
- Benjamin Disraeli
|
|
|
|
|
Why?
File.Replace operates at the Windows OS level.
You're not going to find a "simpler", less "contentious" solution.
Been there; done that.
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
I thought it would save me typing a similar explanation again, although I suppose I could have cut and pasted most of it and edited it where necessary. Anyway, thank you for taking the time to answer my question. It is now working as required.
|
|
|
|
|
"Cut and paste" what?
I still don't see anything that had a bearing on my original response.
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|