Thanks dev leader for sharing this post. Can you please share the image for the happy face you use and let us know the optimal resolution for the images to be used? Your project works fine but the ascii art is not very clear on my laptop. Thanks again
Hey Salam! Sorry for the late response here... My Code Project notifications don't seem to show up in my inbox regularly, so I miss things
I don't actually know where I grabbed the happy face from, unfortunately. And I can't send it here either because we can't attach pictures to the comments.
I was trying pictures that were as big as 1920x1080 and down to 200x200 or so. The source picture needs to have enough variation in the colors to make things stand out because when it's greyscaled and mapped to the small range of characters, it really loses a ton of fidelity
What sort of clarity issues are you encountering? Is the image stretched? If it's not stretched but it's just hard to interpret, it's likely either
1) the source image is too small in resolution
2) the source image doesn't have enough contrast in the colors
A major premise posited in this article seems to be one of teacher/student, and so I would hope the sample code would provide best practices for coding. You can then imagine my surprise in trying to parse a line of code like this:
C#
usingvar inputStream = new FileStream(
imagePath,
FileMode.Open,
FileAccess.Read,
FileShare.Read);
This is in your program.cs translation unit. In this line of code, upon execution completion, inputStream will have had it's Dispose method called since the scope of the using statement has completed. I am guessing this is not your intent - I have to wonder though how this style of coding came to be.
Since experimentation is encouraged, I would like to suggest the following:
After every spot where you have implemented a construct in the form of:
C#
usingvar xxxxx = Method(...);
Add a GC.Collect() call following the method call. From the Microsoft documentation:
Quote:
What does GC collect () do?
It performs a blocking garbage collection of all generations. All objects, regardless of how long they have been in memory, are considered for collection; however, objects that are referenced in managed code are not collected. Use this method to force the system to try to reclaim the maximum amount of available memory.
I think the results might be surprising... I suspect that the program will crash and that you will drop into the debugger.
Hey Stacy, did you try running the code that I provided? The using blocks in this fashion will only Dispose when the variables have gone out of scope. In my program.cs file, the variables for those lines of code you pointed out will not go out of scope until the Main method (implicit in this case) completes.
"I am guessing this is not your intent - I have to wonder though how this style of coding came to be."
My usage of the "using" keyword is exactly as intended here, but I think your assumption about where it's calling Dispose is not what is happening.
To clarify...
There's this:
C#
using (var xxx = new SomethingDisposable())
{
// do something
}
// xxx is out of scope here and will be disposed anyway because we left the using block
There's this:
C#
var xxx = new SomethingDisposable()
using (xxx)
{
// do something
}
// xxx is not out of scope, but the Dispose method was called by exiting the using block
Then there's what I have:
C#
publicvoid SomeMethod()
{
// at this point, we've not initialized the disposable object
SomeOtherMethod();
// at this point, the xxx variable from inside SomeOtherMethod()// has gone out of scope and the using statement will have// triggered the call to Dispose()
}
publicvoid SomeOtherMethod()
{
usingvar xxx = new SomethingDisposable()
// do something// xxx is not out of scope yet and the using statement will not trigger a Dispose call until we leave the method
}
Alright, I wasn't going to bother to respond, as I dislike arrogance, but inasmuch as it seems that Code Project has become increasing a space for that kind of rhetoric, I think this needs to be addressed.
I did try to run the code. No where in the article does it mention what version of C# or the compiler is required, and assuming that the entire development world tracks all of the latest changes in the language is pure hubris. I was not aware that this language change was introduce. If the point of the article is teach, epic fail.
The large majority of real world developers such as myself work for real world clients with real world budgets. That not only translates into what tools we use, but also time and training; not just for ourselves, but for the talent hired. While nifty new language features are great, in this case they do nothing to enhance either readability or best practices. Indeed, Dispose() and GC based memory architecture is an entire subject unto itself, often not implemented correctly, and not something that should be "experimented with". It requires discipline and skill to properly implement.
While I will not get into a general debate about code comments, or when/what to comment, in this case the code screams for a comment when introducing a new breaking change that will not down compile on older IDEs. That's just plain technical developer malfeasance.
Lastly, and perhaps most annoyingly, I could not find a cohesive set of source that could be compiled by even the correct IDE (Git repository?). Seriously, this is 2023.
I've led major teams and major projects, I would never tolerate this kind of behavior. To be clear, I don't have a problem with not being the smartest person in the room -- I actually seek out situations like that, it's the only way to expand one's knowledge base. What I dislike is someone waving their credentials like a shiny bauble to be admired and worshiped. Not I.
Initially, you wrote a lengthy comment about why my using statements do not work. This was the entire focal point of the comment, so I spent time providing different variations of using statements including the behavior of what I have in the article.
Nothing I said was arrogant - and I even spent the time to write out the differences in code behavior and share a link to what I assumed you were having challenges with. After contributing a free article (I'm sorry that this has been a bad experience for you), I spent my own time to try and help explain the cause for what I assumed your confusion was.
For Your List Of Points
1) The "using declaration" feature I am using here is from C# 8. This is from the end of 2019. So 4 years ago. You can see it as one of the features in this list here: The history of C# - C# Guide - C# | Microsoft Learn[^]. And I get it - I wasn't even aware of this syntax until last year. But jumping all the way to making a claim about assuming all developers track the latest changes? We're talking about something from 4 years ago. I can't reasonably understand how you can be so frustrated by this point.
If you took offense to me asking if you ran it - my apologies, but I think it's an entirely valid question based on the claims and suggestions that you provided. And I'm still led to believe that you've not actually had success running this because it sounds like you had compilation issues. So everything that you had suggested in your original comment about why the using declaration syntax doesn't work I'm led to believe is based on assumptions because of this statement:
Quote:
I did try to run the code. No where in the article does it mention what version of C# or the compiler is required
If you had the wrong language version it wouldn't compile. If you had the correct one, you'd observe the proper functionality of the using declaration. I'm open to there being other alternatives, but I still cannot understand the rationale behind being so upset by my response.
I'm happy to update the article to make a note about the using declaration syntax. In fact, I've submit the change before I even post this comment back, but when Code Project editors approve it is on their watch.
I personally think this could have been avoided entirely if you had just asked for clarity about the using declaration syntax if that was the part not compiling for you. Suggesting that the behavior of the code was broken was misleading for me to be able to provide a helpful response.
2) You're reading a free article on the Internet. I'm not forcing you to use the using declaration syntax that was added, it's just what I opted to use in my code. There are trade-offs for everything though. The (seemingly) implicit scope provided by the new using declaration syntax means that for new eyes it's not obvious where the scope ends. However, I assume Microsoft was okay with this as a language feature because where the scope ends *is* predictable: it's the same spot that the variable goes out of scope. With respect to readability, this syntax can reduce nesting which is very helpful for readability.
If you and the team of developers you work with don't agree with that, that's absolutely fine. Readability can be subjective. I'm not forcing you to do anything.
3) I'm not exactly sure how I'm expected to put this point into practice. If I understand correctly, you would like me to add comments to my code in an article about generating ASCII art in C# about using declaration syntax because it could be a breaking change for folks.
As someone producing free articles, how am I to know all of the breaking changes I might have to document for the 8000+ (so far on this site, excluding my own website) readers of this article? Even based on this Stack Overflow answer, the matrix of support for features between language versions and dotnet versions isn't straightforward. What about everyone before .NET 3.5? Is it really my responsibility to go dig up every possible breaking feature across all language versions and write a comment in the code (in my free article) to explain it?
Quote:
That's just plain technical developer malfeasance.
Really? It would be literally impossible for me to do this and try to document every possible thing that might be broken between the current language version and the oldest. It's completely impractical.
Regardless, as mentioned, I took the spirit of your advice and added the section to the article here to call it out for folks. I'm hopeful it helps the next person with using declaration syntax.
4) I suspect I am grossly misunderstanding what this fourth point means. Immediately before introducing any code, I state
Quote:
Let’s look at some code (which, by the way, is available in full on GitHub):
Other than that, I am not sure how else I can properly represent a multi-file project inside of an article. That's why I opted to embed the pieces of code I wanted to discuss further directly in the article and then link to the full set of code right at the start of the example.
Some Other Points
1)
Quote:
If the point of the article is teach, epic fail.
I'm sorry that you've had a bad experience reading my material. I'm not exactly sure why you feel the need to be so rude about someone trying to help bring clarity, but I'll leave that one with you. My apologies that you've had such an awful time reading and engaging here.
2)
Quote:
Seriously, this is 2023.
I hope that my updated explanation about the hyperlink to the entire full solution that you can clone helps with this statement. If you have further suggestions for how I can make it more obvious in my future articles, I'd be open to that feedback.
3)
Quote:
I would never tolerate this kind of behavior.
I am not sure what "kind of behavior" you're referring to with this statement. I wrote you an explanation about using declarations that you appeared to not understand, and then you've now called me arrogant, said my free article has been an epic fail, said that I'm malfeasant for not documenting a language feature, and then of course... this next part:
4)
Quote:
What I dislike is someone waving their credentials like a shiny bauble to be admired and worshiped
I have absolutely no idea where this is coming from. Are you referring to the bio snippet that Code Project puts at the end of the articles? The part where we're supposed to write about ourselves? I don't see anywhere in the article directly where I have mentioned any of my credentials so I am led to believe it's this.
But admired and worshipped? I'm at a loss here. The bio doesn't even have my actual job title/role/position in full, which is arguably even more "shiny". But I'm failing to understand where any of this is being used to demand some type of worship.
In our Code Project settings, it's called our "Professional Profile". So I have some of my professional details set there as we'd be expected to do.
Quote:
I'm a software engineering professional with a decade of hands-on experience creating software and managing engineering teams. I graduated from the University of Waterloo in Honours Computer Engineering in 2012.
Is this truly the part that is "someone waiving their credentials like a shiny bauble to be admired and worshipped"? That I've been in industry for a while and have a degree?
5)
Quote:
This article needs a major shave and a haircut.
I appreciate your feedback and sharing concerns about readers not being familiar with certain language features. Respectfully though, I think you'll have a more enjoyable experience reading someone else's material.