Are C# Static Variable and Methods Evil? Derek Comartin Explains (Video Breakdown)
In the world of C# software development, you’ve likely come across the static keyword — whether in a static void Main, a static variable, or a static method. But are statics always a good idea? Or are they, as some developers warn, dangerous in larger applications?
To get to the truth, we’re going to walk through a detailed video on "Static Variables & Methods are Evil?" from Derek Comartin of CodeOpinion.com, who breaks down the nuanced reasons why static members can become problematic — but not always. We’ll be using his examples and timestamps to guide this in-depth look.
What Makes a Static Method Problematic?
At the start of the video, Derek dives into a static method called Is18YearsOrOlder. This method takes a DateTime birthDate and checks if someone is at least 18. It uses DateTime.UtcNow to compare the current date. Simple enough, right?
But as Derek points out, this method is non-deterministic. At 0:50, he highlights that using DateTime.UtcNow means the method will return different results depending on when you run it. That’s a major issue in unit testing and causes unexpected behavior in code.
In this case, although the method looks like a pure function, it is not. Derek explains that a pure method must return the same value every time it's called with the same parameters. But here, the current date keeps changing, so the return value does too.
This illustrates how a public static method, while convenient, can introduce side effects if it depends on real-time data or application domain state.
Making Static Methods Testable and Predictable
Derek’s next point is crucial: we can fix the non-determinism by removing the dependency on DateTime.UtcNow. Instead, Derek shows how to inject a time provider using a static class or an interface implementation. This makes the function deterministic — you get the same output every time you pass the same input.
In his PlaceOrder class, he introduces a fake date provider so he can test whether orders processed on Fridays get a 50% discount. This avoids hardcoding logic tied to system time, making the method more reliable and testable.
By isolating behavior and avoiding referencing static methods directly inside business logic, Derek shows how to preserve clean code while retaining testability.
Tight Coupling and Static Methods
Derek warns at this point that relying on static methods often introduces tight coupling. If you directly use DateTime.UtcNow, you’re bound to that implementation — you can’t override or mock it.
This is a problem because static members like this are global across your application. If your codebase heavily uses static fields or static properties, it becomes harder to change behavior or inject dependencies, breaking key principles of object-oriented programming.
You also lose flexibility because you can’t substitute that static field with a different implementation, like you could with an instance variable or injected service.
The Global State Problem with Static Variables
Now Derek turns his focus to static variables, and this is where the conversation gets serious.
He presents an example using a static cache in a Global class. He explains that the biggest issue with static variables is unknown state. At runtime, you can’t be sure whether your static field has been initialized. This unpredictability is especially risky when there’s a mutable static int or string name involved.
This scenario becomes worse when developers assume there's only one copy of that variable shared across threads — and forget to account for thread safety.
Thread Safety and Static Fields in Multithreaded Code
Derek brings up another concern: using static variables in multithreaded environments. He gives an example of a static List
To solve this, he switches to a ConcurrentBag
His point is clear: if you’re using static variables across threads, make sure they’re thread-safe. Otherwise, your program can behave unpredictably or even crash.
Safe Use of Static Methods
Derek then shares a safe and effective usage of a static method: a simple utility method MilesToKilometers. It takes an int miles and returns a double value after conversion. This method is deterministic — for the same int value, you always get the same result.
This kind of method doesn't rely on non-static fields, doesn’t mutate shared data, and doesn’t involve any unknown state. It’s a great example of how to properly use the static keyword in C#.
Understanding Static in the .NET Context
In C#, the static keyword can be applied to classes, fields, methods, constructors, and properties. Derek indirectly touches on the concept of:
Static class: A class that cannot be instantiated and can only contain static members.
Static fields: Declared with static keyword — only one copy exists per application domain.
Static constructor: Runs only once when the class is first accessed.
Static void Main: The entry point of most C# applications, demonstrating how static methods can be essential.
- Static int, static string: Examples of static fields that store data common to all instances of the class, or in fact, don’t require an instance at all.
Unlike instance constructors which run every time you create an object, the static constructor only initializes the class-level resources once.
This distinction helps developers decide when to use instance variable vs. static variable, or when to use property accessors for encapsulating shared member variables.
Final Takeaways from Derek
Derek summarizes the main reasons why developers caution against static members:
Tight coupling — you're stuck with the behavior of that static method or field.
Non-deterministic behavior — hard to test, easy to break.
Global mutable state — you don’t know what the value is or who changed it.
- Concurrency issues — unsafe access to shared data in multithreaded code.
Yet, as Derek says, static isn’t evil. It's powerful when used correctly — especially in utility functions, shared constants, or truly global settings. You just need to manage state carefully and avoid depending on mutable or system-specific behavior.
Conclusion
Static variables and methods are a double-edged sword in C#. As Derek Comartin clearly explains, they’re not inherently bad — but they require thoughtful usage. Use static fields and static classes when you need shared data or functionality that doesn't depend on object state. But avoid using them for things that depend on time, system state, or require flexibility.
So before you create an object or access a static field, think about scope, testability, thread safety, and whether the code needs one copy or multiple instances.
Watch Derek Martin’s full video on his CodeOpinion YouTube channel. You'll find more insights on clean architecture, software design, and real-world C# applications.
