[Proposal] Generic Type Parameters for Namespaces. #7831
Replies: 2 comments 9 replies
-
You could do this with nested classes. static class Math3D<T> where T : IFloatingPoint<T>
{
public struct Point3D(T x, T y, T z)
{
public T X { get; set; } = x;
public T Y { get; set; } = y;
public T Z { get; set; } = z;
public static Point3D operator +(Point3D<T> p, Vector3D v) => new Point3D(p.X + v.I, p.Y + v.J, p.Z + v.K);
public static Vector3D operator -(Point3D<T> p1, Point3D p2) => new Vector3D(p1.X - p2.X, p1.Y - p2.Y, p1.Z - p2.Z);
}
public struct Vector3D(T i, T j, T k)
{
public T I { get; set; } = i;
public T J { get; set; } = j;
public T K { get; set; } = k;
}
public struct Matrix4
{
public Point3D Transform(Point3D point)
{
//You get the idea...
return new Point3D(point.X, point.Y, point.Z);
}
}
} Namespaces don't really exist as far as the runtime is concerned. They are part of the type name themselves. |
Beta Was this translation helpful? Give feedback.
-
I'm sorry, but that's simply not true. The syntax declares it as generic implicitly by A) being defined within the scope of a namespace that has been decorated with generic type parameters and B) making use of one or more of those type parameters within the class somewhere. While it's not explicit definition as you would see today it is definitely not magic out of nowhere... the author has to do something visible within the code to cause the behavior. This is what evolving language syntax looks like... it's a new way to do something different than how you might do it today.
Again... we're talking about evolving syntax of a language. Most of your concerns have fallen under the general category of "but that's not how C# does that... why not just do it the long and verbose way that is already supported?" By that logic why should we even have auto properties, record types, extension methods, lambda expressions, primary constructors, initializers? ALL of these things were possible with the language in some way before they existed. NONE of these features added any functionality beyond quality of life...Why have any of them been added to the language? I understand you may not like the proposal, that's fine. And I do appreciate the discussion, it's made me think about what I'm proposing and other shortcomings it may have... I will say, however, that this proposed syntax would be just as optional as any other syntax sugar that has been added to the language over the 20+ years I've been using it. Don't like var? don't use it! Want to manually specify backing fields for all of your properties? knock yourself out! Think extension method "lie" about what methods are available in a given type? Don't use them.... |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
This proposed feature allows for a handy design pattern where a library can provide generic implementations of types that should always be used together with the matching type parameters. This idea flows from my use of the numerical interfaces introduced in .NET 7 hence my example code... This feature is mostly "syntax sugar" as it doesn't provide any capability that you can't achieve with the language today, it just makes the code cleaner and communicates intent better.
NOTE: This is really not useful for single stand-alone Generic types that we are used to using. Things like
List<T>
orSpan<T>
. In these cases there is no value in specifying a shared generic type parameter since these types are often used in isolation and a single method may use several concrete types with different type parameters (List<int>()
List<SomeClass>()
, etc... ) Rather, this feature is for groups of types that regularly interoperate with each other and need to keep consistent generic type parameters between them. In addition, it only makes sense if a particular file ALWAYS uses the same type parameter when using these types so you end up specifying the same parameter over and over again.Here's an example of how it would work. Assume we're dealing with a basic 3D math library and I want to support both single and double precision floating point values for all of my types.
Today I can do this:
Usage (notice how I have to keep specifying double everywhere):
This is what I propose as an alternative:
Now the generic type parameter T is specified once at the namespace definition (along with the constraint). I can then use T anywhere within the types contained in the namespace and it will be resolved to the same type.
New Usage:
The main drawback/hurdle I see is if for some reason someone wants to use the same namespace with two different parameters within the same file (mixing single and double precision 3D Math?). In these cases it should be possible to create an alias for the namespace with the generic parameters resolved like this:
Beta Was this translation helpful? Give feedback.
All reactions