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)