Stopwatch class without using System.Diagnostics in C# 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() =&gt; (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() =&gt; Stopwatch.RunProgram();
    }
}
public static void RunProgram()
{
   ....
}



Why do you run the application as a method on the Stopwatch class it self?



You have made all the methods (StartTimer(), StopTimer()) private. This means that they only can be run from your RunProgram method, which occupy the main thread of the program and measures nothing. This set up makes the entire effort rather useless. I would expect a stopwatch being able to measure something in a way like:

  Stopwatch stopwatch = Stopwatch.StartNew();

  // TODO: execute something you want to measure
  Thread.Sleep(5000);

  stopwatch.Stop();

  Console.WriteLine($"Duration: {stopwatch.Duration}");





    private static bool isStarted = false;
    private static bool isStopped = false;



These flags can be combined into one isRunning, used like:

    private static void StartTimer(DateTime start)
    {
        if (isRunning)
        {
            throw new InvalidOperationException("Unable to start a stopwatch twice in a row.");
        }
        else
        {
            isRunning = true;
            TimeStart = start;
        }
    }


and

    private static void StopTimer(DateTime stop)
    {
        if (!isRunning)
        {
            throw new InvalidOperationException("Unable to stop the stopwatch because it is not running.");
        }
        else
        {
            isRunning = false;
            TimeStop = stop;
        }
    }





    private static void Begin()
    {
        StartTimer(DateTime.Now);
        System.Console.WriteLine(" - Stopwatch has begun.");
    }



You shouldn't write to the console in class methods of any object, unless it's explicitly meant to be a console application. The above message is useless in a WinForm application.




  private static void StartTimer(DateTime start)


I don't se why you have a start time as argument to StartTimer. Why not just call DateTime.Now inside it? And likewise in StopTimer.



You were told to provide the result as a TimeSpan, but you actually return a string:


  private static string ElapsedTimer() =&gt; (TimeStop - TimeStart).ToString();





  public static class Stopwatch


The major problem with your implementation is though, that you make it static. That means that you only can run one "instance" at a time. In this way you aren't able to measure on two treads at the same time - or have nested measurements.

I would remove all the static stuff and only have one static method - starting a new Stopwatch instance, that then can be stopped by calling Stop() on the returned object like I showed above. So the public interface of the object would be:

  public class Stopwatch
  {
    public TimeSpan Duration { get; }

    public void Start() { }
    public void Stop() { }
    public static Stopwatch StartNew() { }
  }


I think you have misunderstood the concepts of "encapsulation and information hiding" slightly. An object must have a public interface through which clients can communicate with it, but they shouldn't be allowed to manipulate the objects internal state (for instance the StartTime member of your watch) - only through the public interface. The client shouldn't know about how you measure the time internally, they are only interested in the final result, when they stop the watch by calling Stop().