DEV Community

Cover image for Static + Generics = Trouble? Why Your C# Code Smells and How to Clean It Up
Jose Rodriguez Marrero
Jose Rodriguez Marrero

Posted on

Static + Generics = Trouble? Why Your C# Code Smells and How to Clean It Up

So there I was… writing some C# code for my, minding my own business, when bam — the compiler drops this wisdom on me:

⚠️ CA1000: Do not declare static members on generic types

And I’m like...

“Okay compiler, but can you explain that like I’m five?”

Let’s break it down.


🍱 Static + Generics: What’s Actually Going On?

You might write something like this:

public class SnackBox<T> { public static int SnackCount; } 
Enter fullscreen mode Exit fullscreen mode

Seems harmless. But if you use it like this:

SnackBox<string>.SnackCount = 5; SnackBox<int>.SnackCount = 10; Console.WriteLine(SnackBox<string>.SnackCount); // 5 Console.WriteLine(SnackBox<int>.SnackCount); // 10 
Enter fullscreen mode Exit fullscreen mode

You suddenly realize: 😱 Each version of T gets its own static member.
So now you’ve got dozens of mini snack boxes floating around in memory — each hoarding their own SnackCount.


🧽 What This Has To Do With Real Code

Let’s say you’re writing a helper to apply specs to a query:

public static class SpecificationEvaluator<T> where T : BaseEntity { public static IQueryable<T> GetQuery(IQueryable<T> query, ISpecification<T> spec) { if (spec.Criteria != null) { query = query.Where(spec.Criteria); } return query; } } 
Enter fullscreen mode Exit fullscreen mode

Looks fine, right?

Well, sort of. But this triggers CA1000, and for good reason:

  • You now have a separate static class per type — e.g., SpecificationEvaluator<Product>, SpecificationEvaluator<Order>, etc.

  • That increases memory usage

  • It’s harder to use (you have to specify the type every time)

  • And worst of all... the compiler is silently judging you 😬


🧹 The Fix: Static Class, Generic Method

We can clean this up by moving the generic parameter from the class to the method:

public static class SpecificationEvaluator { public static IQueryable<T> GetQuery<T>(IQueryable<T> query, ISpecification<T> spec) where T : BaseEntity { if (spec.Criteria != null) { query = query.Where(spec.Criteria); } return query; } } 
Enter fullscreen mode Exit fullscreen mode

Now you can call it like:

var result = SpecificationEvaluator.GetQuery(products, productSpec); 
Enter fullscreen mode Exit fullscreen mode
  • No generic class instantiations

  • Cleaner syntax

  • The compiler stops yelling 🎉


✅ TL;DR — What Did We Learn?

❌ Don’t Do This ✅ Do This Instead
static class MyHelper<T> static class MyHelper
Static method inside generic class Generic static method inside static class
One copy per T One reusable method for all types
CA1000 warning ✨ No warning, no surprises ✨

🎯 Final Thoughts

If you've ever been confused by that CA1000 warning or wondered why your static generic utility felt “off,” you’re not alone.

Just remember:

Static classes are like toolboxes.
You don’t need a separate toolbox for every kind of screw. 🧰

Happy coding! 👨‍💻👩‍💻
Have you encountered CA1000 before? Drop a comment — I'd love to hear your story or tips!

Top comments (0)