30

I've a generic class that helps me to do checks on argument values:

internal sealed class Argument<T>
    where T : class
{
    private void TraceAndThrow(Exception ex)
    {
        new InternalTraceHelper<T>().WriteError(ex);
        throw ex;
    }

    internal void ThrowNull(object value, string argName)
    {
        if (ReferenceEquals(value, null))
        {
            TraceAndThrow(new ArgumentNullException(argName));
        }
    }

    internal void ThrowIf(bool condition, string argName)
    {
        if (condition)
        {
            TraceAndThrow(new ArgumentException(null, argName));
        }
    }


    internal void ThrowNotInEnum(Type enumType, object value)
    {
        if (!Enum.IsDefined(enumType, value))
        {
            TraceAndThrow(new ArgumentOutOfRangeException(Resources.ArgEnumIllegalVal.InvariantFormat(value)));
        }
    }
}

But when I try to use it with a static class:

internal static class Class1
{
    private static Argument<Class1> _arg;
}

I got this error (at compilation):

static types cannot be used as type arguments

What am I doing wrong?

Pang
  • 9,564
  • 146
  • 81
  • 122
Arnaud F.
  • 8,252
  • 11
  • 53
  • 102

5 Answers5

36

This is deliberate.

Static classes try to prevent inappropriate use, so in almost all situations, you can't use them in situations where you'd normally want an instance of the type... and that includes type arguments.

See section "Static classes" of the C# 6 spec for the very limited set of situations in which you can refer to static class types.

ehiller
  • 1,346
  • 17
  • 32
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Doing my static classes non static but with a private constructor will do the job? So no one can instanciate it, but is non-static. Is this a good way to perform it? (Thanks for the section, I've read it) – Arnaud F. May 02 '11 at 15:02
  • @Arnaud F.: Well that would *work* - but what are you using the type argument for? What's the point of it? It looks like it's only used by `InternalTraceHelper`, and we don't know what that's like. – Jon Skeet May 02 '11 at 15:04
  • `InternalTraceHelper` does `Trace.Write()`, the argument type is used to define the category of the trace. Can be replaced by `Trace.WriteLine("a message", typeof(T).FullName); // Where T = Class1` – Arnaud F. May 02 '11 at 15:08
  • 6
    @Arnaud F.: It sounds like you possibly want a non-generic version of InternalTraceHelper which takes a `Type` instead. In fact, you could make the whole class non-generic, just with a generic method to make creation simpler: `InternalTraceHelper.Create` would call `new InternalTraceHelper(typeof(T))` where `T` is the type parameter for the method. – Jon Skeet May 02 '11 at 15:10
  • 2
    Thanks a lot for the tip Master ! – Arnaud F. May 02 '11 at 15:12
5

Generics only work with instances, not static classes.

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
  • Is there a workaround? How can I manage it? I wouldn't check "manually" in static classes and using `Argument` in the non-static one... – Arnaud F. May 02 '11 at 14:50
  • No there isn't other than using `System.Type`. – Daniel A. White May 02 '11 at 14:52
  • @Arnaud, you can't pass static types as arguments, so I fail to see when you'd ever want to have an `Argument`, unless I'm being misled by your class name. – JSBձոգչ May 02 '11 at 14:53
  • Doing my static classes non static but with a private constructor will do the job? So no one can instanciate it, but is non-static. Is this a good way to perform it? – Arnaud F. May 02 '11 at 14:53
  • yeah this is definitely an informative answer. why did u bother to write such a long text ? – Selman Genç Apr 20 '17 at 16:01
2

Since static classes cannot be instantiated, it can never create Argument<T> with a static type.

Bala R
  • 107,317
  • 23
  • 199
  • 210
  • 10
    That is incorrect. ILogger is an example where the class becomes a category for the logger to use when emitting diagnostics. This is a stupid rule. – Quark Soup Apr 04 '19 at 12:31
  • 1
    @Quarkly, did you find a way around it? considering just making the class non-static now – ElFik Jan 17 '20 at 18:44
0

What you are doing wrong is using a static type as a generic type argument.

Mark Cidade
  • 98,437
  • 31
  • 224
  • 236
0

Since static classes won't have instance members, my concern would be what kind of thing I'm going to do with them.

I believe that, missing that you can't use static classes as generic arguments, I believe that you need to do this with extension methods instead of a generic class.

https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods

Pang
  • 9,564
  • 146
  • 81
  • 122
Matías Fidemraizer
  • 63,804
  • 18
  • 124
  • 206