Design a class called Stopwatch. The job of this class is to simulate a stopwatch. It should provide two methods: Start and Stop. We call the start method first, and the stop method next. Then we ask the stopwatch about the duration between start and stop. Duration should be a value in TimeSpan. Display the duration on the console. We should also be able to use a stopwatch multiple times. So we may start and stop it and then start and stop it again. Make sure the duration value each time is calculated properly. We should not be able to start a stopwatch twice in a row (because that may overwrite the initial start time). So the class should throw an InvalidOperationException if its started twice.
The aim of this exercise is to make you understand that a class should be always in a valid state. We use encapsulation and information hiding to achieve that. The class should not reveal its implementation detail. It only reveals a little bit, like a blackbox. From the outside, you should not be able to misuse a class because you shouldn’t be able to see the implementation detail.
That is the information given to me from the tutorial I am taking to teach myself C#. I have completed this and looking for ways to improve my code and/or learn something new here. I have tested this and to my knowledge is working as expected. Any help is appreciated.
using System;
namespace ExerciseOne
{
public static class Stopwatch
{
private static DateTime TimeStart { get; set; }
private static DateTime TimeStop { get; set; }
private static bool isStarted = false;
private static bool isStopped = false;
private static void StartTimer(DateTime start)
{
if (isStarted)
{
throw new InvalidOperationException("Unable to start a stopwatch twice in a row.");
}
else
{
isStarted = true;
isStopped = false;
TimeStart = start;
}
}
private static void StopTimer(DateTime stop)
{
if (isStopped)
{
throw new InvalidOperationException("Unable to stop a stopwatch twice in a row.");
}
else
{
isStarted = false;
isStopped = true;
TimeStop = stop;
}
}
private static string ElapsedTimer() => (TimeStop - TimeStart).ToString();
private static void Begin()
{
StartTimer(DateTime.Now);
System.Console.WriteLine(" - Stopwatch has begun.");
}
private static void End()
{
StopTimer(DateTime.Now);
Console.WriteLine($" - Stopwatch has stopped. Elapsed Time: {ElapsedTimer()}");
}
public static void RunProgram()
{
Console.WriteLine("Stopwatch program.");
Console.WriteLine("Type \"S\" to start the program. Type \"T\" to stop the program. Type \"E\" to end the program.");
while (true)
{
ConsoleKeyInfo cki = Console.ReadKey(false);
if (cki.Key == ConsoleKey.E)
{
Console.WriteLine(": \"E\" key was pressed. Progam exited.");
return;
}
else if (cki.Key == ConsoleKey.S)
{
Begin();
}
else if (cki.Key == ConsoleKey.T)
{
End();
}
else
{
Console.WriteLine("\nPlease type either \"S\" to start the program, \"T\" to stop the program, \"E\" to end the program.");
}
}
}
}
}
using System;
namespace ExerciseOne
{
class Program
{
static void Main() => Stopwatch.RunProgram();
}
}
Stopwatch
is commonly used as a high resolution timer. The answers I see here do not address that issue. If you don't care, you can use theDateTime
class and properties, but be aware they will be nowhere near as accurate asStopwatch
. If you need a high resolution example I can write an answer. \$\endgroup\$System.Diagnostics.Stopwatch
. \$\endgroup\$Stopwatch
. \$\endgroup\$