Yushatak Yushatak - 3 months ago 7
C# Question

Class<T> and static Class, Best Practices?

I have a scenario that (simplified) is as follows:

public static class Example
{
public const int CONSTANT_VALUE = 1;

public static Example<T> Create<T>(IEnumerable<T> argument)
where T : class
{
return new Example<T>(argument);
}

//More overloads of Create<T>, possibly other static methods, etc..
}

public class Example<T>
where T : class
{
public Example(IEnumerable<T> argument)
{
//Do Stuff

//Nothing like this in the real code, just example
//that constants are used from the other class.
if (something == Example.CONSTANT_VALUE)
{
//Do A Thing
}
}

//Lots more code
}


The basic idea is that I can have static methods, constants, etc. available through the name of the class through the static class, while the actual implementation is in the type-argumented non-static class.

My question is whether or not this is a good way to set this up. Is there a way to put some static methods and constants that don't care what the type argument is on
Example<T>
? Is there otherwise a more recommended pattern? What I have works fine, but I wanted to know if there are other ways since this is the first time I've ended up doing something like this (not that it's conceptually new to me, just never had need).

Answer

This would only make sense if the constants are public. If they are only for internal use inside Example<T> then this is pointless, becuase you can reference them without a fully qualified name.

If the constants are of public use, I wouldn't use this pattern anayways; Example and Example<T> are two different classes, it is potentially confusing to any user, and not immeadiately obvious, that constants defined in the non generic class are aplicable to the generic one.

You are only avoding the user a few keystrokes, I'm not really sure it is worth it.

Update: other options

In this scenario, I'd use the following factory pattern (assuming the users are outside your assembly)

public class Example<T>
{
     internal Example() { } //disallow users from instantiating this class
      ...
}

public static class Example
{
    public const int Constant = ...
    public static Example<T> Create<T>() { return new ... }
}

And now all users will interact only with Example and avoid using Example<T>. You could even enforce this with users of your own assembly, you'd just need to make Example<T> a private nested class implementing a public interface:

 public interface IExample<T>
 {
     ...
 }

 public static class Example
 {
     private class Example<T>: IExample<T> { ... }
     public static IExample<T> Create<T>() { ... }
     ....
  }
Comments