If I implement a generic type that risks being instantiated with lots of type params, should I avoid (for JIT performance/code size etc. reasons) having many nested non-generic types?
Example:
public class MyGenericType<TKey, TValue>
{
private struct IndexThing
{
int row; int col;
}
private struct SomeOtherHelper
{
..
}
private struct Enumerator : IEnumerator<KeyValuePair<TKey, TValue>> { }
}
The alternative which works equally well is to have the non-generic types outside, but then they pollute the namespace. Is there a best practice?
public class MyGenericType<TKey, TValue>
{
private struct Enumerator : IEnumerator<KeyValuePair<TKey, TValue>> { }
}
internal struct IndexThingForMyGenericType
{
int row; int col;
}
internal struct SomeOtherHelper
{
...
}
Generics in C# is its most powerful feature. It allows you to define the type-safe data structures. This out-turn in a remarkable performance boost and high-grade code, because it helps to reuse data processing algorithms without replicating type-specific code.
Generics enable the use of stronger type-checking, the elimination of casts, and the ability to develop generic algorithms. Without generics, many of the features that we use in Java today would not be possible.
A generic class and a generic method can handle any type of data.
Only reference types can be used as type arguments. A parameterized type such as List<int> or Set<short> is illegal. Only reference types can be used for instantiation of generic types and methods.
In C# every nested type of a generic type is inherently generic. Compiler will make the nested type as generic too(without our knowledge). Refer this article for more info.
Although generics shares JIT code for reference types as explained in this interview, it has some overhead compared to non generic classes. Each value type gets its own JIT code.
If the type is used only in the generic class --It makes more sense to be a private nested type.
If the type is used elsewhere, then it should ideally be a non nested type (as internal).
That said, if your nested types isn't using the Type Parameter T
in this case, it doesn't needs to be a nested type of generic type and thus it becoming a generic type as well.
Most of the time it shouldn't matter but if you're concerned of many types created at runtime, you can refactor your generic type to have a non generic base class which acts as a container type for your nested types and expose the nested types as protected.
public class NonGenericBase
{
protected struct IndexThing
{
int row; int col;
}
protected struct SomeOtherHelper
{
..
}
}
public class MyGenericType<TKey, TValue> : NonGenericBase
{
private struct Enumerator : IEnumerator<KeyValuePair<TKey, TValue>> { }
}
This way you're sharing the same nested types. No runtime overhead. No separate types for each type parameter. Now typeof(MyGenericType<int, string>.SomeOtherHelper)
will be equal to typeof(MyGenericType<long, bool>.SomeOtherHelper)
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With