Console.WriteLine & Debugger not working on Windows/VSC? - c#

I'm following a C#/.NET PluralSight tutorial (building a gradebook) and for some reason, my first 'Console.WriteLine(result)' isn't displaying anything when I use the "Start without Debugging" option. The second Console.WriteLine works fine.
Also, the debugger doesn't work; I set a breakpoint and the debugger runs without stopping and finishes without any errors. I'm working in Visual Studio code. Thoughts?
using System;
namespace GradeBook
{
class Program
{
static void Main(string[] args) //this is a method
{
var numbers = new[] {12.7, 10.3, 6.11, 4.1};
var result = 0.0;
foreach(double number in numbers) {
result += number;
}
Console.WriteLine(result);
if(args.Length > 0) {
Console.WriteLine($"Hello, {args[0]} !");
} else {
Console.WriteLine("Hello!");
}
}
}
}

At the end of your main method put Console.ReadKey();

I think you should put Console.ReadLine(); after the if-else statement. There's other way too, but I used to code this line.

Related

How to recursively return all args inputs in C#

I'm new to C# and have been testing ways to make the classic Hello World a little more dynamic. So far, I have it set up to test if there even is an args input but I can only get it to return the first without hard coding args[1] - args[x]. I tried messing around with the idea of using tuples but I'm clearly not sure
static void Main(string[] args)
{
if (args.Length > 0)
{
Console.WriteLine($"Sup, {args[0]}");
}
else
{
Console.WriteLine($"Hello World");
}
}
A very simple solution is to use string.Join to do this:
Console.WriteLine($"Sup, " + string.Join(", ", args));
This
Concatenates the string representations of an array of objects, using the specified separator between each member.
It is perfectly fine to call Main recursively - there is nothing special about it short of it being called at a startup.
static void Main(string[] args)
{
if(args.Length == 0)
{
Console.WriteLine($"Hello World");
return;
}
Console.WriteLine($"Sup, {args[0]}");
if (args.Length > 1)
{
// recursively call Main with the remaining args, note that recursive
// call will not hit "Hello world" case as the tail always has at least one element
Main(args.Skip(1).ToArray());
}
}
Note that it is quite inefficient as it creates multiple arrays, passing index where to start could be an option but it would change signature of Main and as result will require one more function. If you simply want to access arguments String.Join as shown in other answer or for(int i =0; i<args.Length; ++) {Console.Write(args[i]);} would be much more common approach.

Why does this program enter the if block in Release build but not in Debug build?

I have some code that behaves differently between a Release build and a Debug build. It behaves correctly in Debug but not in Release.
I have a function that returns a ReadOnlyCollection<MyCustomClass>. One section is this:
var result = new List<MyCustomClass>();
...
var list1 = this.returnEmptyList();
var list2 = this.returnListWithOneItem();
if (list1.Count == 0 && list2.Count == 0)
{
functionOutVariable = string.Empty;
return result.AsReadOnly();
}
For the purposes of troubleshooting I've simplified the code and named the variables in a generic fashion, and the methods returnEmptyList and returnListWithOneItem are shown here:
private List<string> returnEmptyList()
{
return new List<string>();
}
private List<string> returnListWithOneItem()
{
return new List<string> {"something"};
}
Clearly it should never enter the if block because list2.Count should always be 1, but when I execute this in a Release build, it does:
So there's clearly some optimization going on since you can see that list1 is inaccessible, and when stepping through it executed line 416 and then jumped immediately to line 421. I should state that all the assemblies in my solution use .NET Framework 4.6.2, and I'm running Visual Studio 2017 version 15.3.5.
When I change the build to Debug and execute this, it executes line 416, 417, and on line 418 it shows list1.Count is 0 and list2.Count is 1, and it correctly does not enter the if block.
I'm trying to make a test project to reproduce this but I can't. I'm looking for any way to get to the bottom of this. I don't just want a fix that makes it go away - I need to understand what I'm doing wrong.
Ok, I'm pretty sure it's a result of a subtle bug in the rest of my function that allowed the compiler to just optimize out the if block and return early. I can reproduce the behavior of the debugger in this test project, and it totally makes sense in this case:
class Program
{
static void Main(string[] args)
{
var test = new MyClass();
test.DoTest(out var result);
Console.WriteLine(result);
Console.ReadKey();
}
}
class MyClass
{
public ReadOnlyCollection<MyCustomClass> DoTest(out string functionOutVariable)
{
var result = new List<MyCustomClass>();
var list1 = this.returnEmptyList();
var list2 = this.returnListWithOneItem();
if (list1.Count == 0 && list2.Count == 0)
{
functionOutVariable = string.Empty;
return result.AsReadOnly();
}
functionOutVariable = string.Empty;
return result.AsReadOnly();
}
private List<string> returnEmptyList()
{
return new List<string>();
}
private List<string> returnListWithOneItem()
{
return new List<string> { "something" };
}
}
class MyCustomClass
{
}
When I execute in a Release build with the debugger, it appears to enter the if block, but in reality it just optimized out the if block completely and the debugger confusingly shows it executing the lines inside the if block instead of jumping over it:
Edit: I've confirmed there was a bug later in the function that was causing my problem, and the behavior of the debugger when looking at Release build code was just causing me confusion, due to compiler optimizations.
To be clear, my question is incorrect: the function was actually giving the same result in both Release and Debug builds but I was mistaken. That's because I followed this (flawed) sequence:
I had a failing test (against a Release build).
I ran the test with the debugger (still in Release build) and saw it apparently go into the if block incorrectly.
I then switched the build to Debug and ran the test with the debugger and saw it step over the if block. I assumed (incorrectly) that was the source of my problem.
That sent me on the wild goose chase seen above. Sorry for wasting your time, but I certainly found the exercise informative. Perhaps someone else will learn from my mistake in the future. :)

What is and is not recursion?

I'm trying to understand what exactly is recursion and have not been able to find an answer to the following.
My current understanding of recursion is that it is anytime a method calls itself.
I.E
Menu()
{
if(i<2)
{Console.WriteLine();}
else
{Menu();}
}
The above is an example of recursion a method calling itself.
What I'm not sure about is a scenario like:
Menu()
{
if(i<2)
{Console.WriteLine();}
else
{Console.WriteLine("Something Went Wrong!"); MenuError();}
}
MenuError()
{
Console.WriteLine("Something went wrong!");
Menu();
}
If the method calls a method which then calls it is this still recursion ?
My current understanding of recursion is that it is anytime a method
calls itself.
That is correct. Recursive definitions are self-referencing definitions.
Two interesting properties of recursive definitions are productivity and termination. A program is productive if it continues to yields output, though the full output may never come (hence it may not terminate). A program terminates if it yields its full output in finite time.
For example, this is a productive, non-terminating program:
Naturals(int i) {
Console.WriteLine(i);
Naturals(i + 1);
}
This is a terminating program:
UpToTen(int i) {
Console.WriteLine(i);
if (i < 10) UpToTen(i + 1);
}
This is a non-productive program:
DoNothing() {
DoNothing();
}
If Menu calls MenuError, and MenuError calls Menu, this is sometimes called mutual recursion. The only difference is our organisation; we can rewrite the code to just have one method by inlining MenuError.
Menu() {
if (i < 2) {
Console.WriteLine();
}
else {
Console.WriteLine("Something Went Wrong!");
Console.WriteLine("Something went wrong!");
Menu();
}
}
You can in fact abstract recursion itself:
// General definition
A Fix<A>(Func<Func<A>,A> f) {
return f(() => Fix(f));
}
// Special definition for void functions
void Fix(Action<Action> f) {
f(() => Fix(f));
}
void Menu(Action menu) {
if (i < 2) {
Console.WriteLine();
}
else {
Console.WriteLine("Something Went Wrong!");
Console.WriteLine("Something went wrong!");
menu();
}
}
Fix(Menu);
Here is another example using Fix to define the factorial function.
Func<int, int> Fac(Func<Func<int, int>> fac) {
return i => i == 0 ? 1 : i * fac()(i - 1);
}
// Fix<Func<int, int>>(Fac) is the factorial function
You may wonder why Fix does not have the signature A Fix<A>(Func<A,A> f) instead. This is because C# is a strict language, meaning it evaluates arguments before it evaluates function application. With the simpler signature the C# program would end up in infinite recursion.
Yes it is still recursion. There are different types of recursion like Tail recursion, Tree Recursion etc. You can check out google for rest.
By the way, in the second case, if value of i is greater than or equal to 2, you will get stack overflow error as each one will call another one.

Time required for a process to complete

I am new to C# world. I am attempting to calculate time taken by a algorithum for the purpose of comparison. Following code measures the elapsed time from when a subroutine is called until the subroutine returns to the main program.This example is taken from "Data structures through C#" by Michael McMillan.
After running this program the output is Time=0, which is incorrect. The program appears to be logically correct. Can anybody help me. Following is the code
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Chap1
{
class chap1
{
static void Main()
{
int[] nums = new int[100000];
BuildArray(nums);
Timing tObj = new Timing();
tObj.startTime();
DisplayNums(nums);
tObj.stopTime();
Console.WriteLine("Time: " + tObj.result().TotalSeconds);
Console.WriteLine("Start Time: " + tObj.startTime().TotalSeconds);
Console.WriteLine("Duration : " + tObj.result().TotalSeconds);
Console.ReadKey();
}
static void BuildArray(int[] arr)
{
for (int i = 0; i <= 99999; i++)
arr[i] = i;
}
static void DisplayNums(int[] arr)
{
for (int i = 0; i <= arr.GetUpperBound(0); i++)
Console.WriteLine(arr[i]);
}
}
class Timing
{
TimeSpan StartTiming;
TimeSpan duration;
public Timing()
{
StartTiming = new TimeSpan(0);
duration = new TimeSpan(0);
}
public TimeSpan startTime()
{
GC.Collect();
GC.WaitForPendingFinalizers();
StartTiming = Process.GetCurrentProcess().Threads[0].UserProcessorTime;
return StartTiming;
}
public void stopTime()
{
duration = Process.GetCurrentProcess().Threads[0].UserProcessorTime.Subtract(StartTiming);
}
public TimeSpan result()
{
return duration;
}
}
}
The Stopwatch class is designed for this.
UserProcessorTime doesn't begin to have the resolution necessary to measure counting to 100000 in a for loop. Your WriteLine calls won't be included in user time as they are I/O time. Your code might not be running on thread 0. User time isn't updated except at context switches. When you print startTime, you're changing the stored value. There are probably some other things that can go wrong I haven't thought of.
I strongly suggest you use the Stopwatch class which takes advantage of the CPU's performance counters.
You don't use the Timing class anywhere in your main function and I don't see where you print the time either. Is this the EXACT code you're running?
Update per new code:
Don't run it in debug mode... build your release version and then run the executable manually: http://social.msdn.microsoft.com/forums/en-US/vbgeneral/thread/3f10a46a-ba03-4f5a-9d1f-272a348d660c/
I tested your code and it worked fine when running the release version, but when I was running it in the debugger it was not working properly.

Debugger does not hit breakpoint

I found something quite odd(I think!). If I try to put a breakpoint in the yes() method, it will never pause the program when it executes the function. If I try to do the same to any other line of code, it will work just as expected. Is it a bug, or is there something that's escaping me?
The filter will return the 2 objects, everything seems to be working as expected except the debugger.
private void Form1_Load(object sender, EventArgs e) {
List<LOL> list = new List<LOL>();
list.Add(new LOL());
list.Add(new LOL());
IEnumerable<LOL> filter = list.Where(
delegate(LOL lol) {
return lol.yes();
}
);
string l = ""; <------this is hit by the debugger
}
class LOL {
public bool yes() {
bool ret = true; <---------this is NOT hit by the debugger
return ret;
}
}
Enumerable.Where is a lazy operator -- until you call something that goes through the IEnumerable returned by where (ie. calling .ToList() on it), your function won't get called.
Try changing your code to this and see if it gets called:
....
IEnumerable<LOL> filter = list.Where(
delegate(LOL lol) {
return lol.yes();
}
).ToList();
string l = "";
You have to materialize the list. Add a ...
filter.ToList();
... after the declaration and you will hit your breakpoint. About the best discussion I've seen on that is here. It does lazy evaluation much better justice than I could do.
As others have said, you have just defined your criteria but have not asked it for execution. This is called lazy loading (guys, correct me if I am wrong).
Run a foreach loop on filter to see what happens.
Jonathan is correct.
Try running this console application and set breakpoints where indicated to see it clearly.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List<LOL> list = new List<LOL>();
list.Add(new LOL());
list.Add(new LOL());
IEnumerable<LOL> filter = list.Where(
delegate(LOL lol)
{
return lol.yes();
}
);
// Breakpoint #2 will not have been yet.
Console.Write("No Breakpoint"); // Breakpoint #1
// (Breakpoint #2 will now be hit.)
Console.Write("Breakpoint! " + filter.Count());
}
class LOL
{
public bool yes()
{
bool ret = true; // Breakpoint #2
return ret;
}
}
}
}

Categories

Resources