-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Proposal]: Support generics and generic type parameters in aliases #3993
Comments
Alternatively, as an addendum to the syntax proposed by #116 this could be changed to use partially bound type names. If that proposal were implemented this is likely the changes that would need to be made to it in order to add support for partially bound aliases short of having two separate generic alias syntaxes: using StringDictionary<> = System.Collections.Generic.Dictionary<string,>; |
I don't see this proposal as an alternative to #116, but rather as a separate feature request intended to solve a different problem -- specifically the ability to use partially-bound generic using directives. |
Perhaps. Given the overlap between the two I feel that it is probably more appropriate to approach them as alternatives. If #116 were to be implemented (or was already implemented) I don't feel that a completely separate syntax such as this would be appropriate and I would instead be pushing for further evolution of your proposal in a similar vein to the first comment I made to this proposal. |
@HaloFour 👍 I love this. I would use it constantly. |
👍 This is an excellent idea. |
I believe there is a problem with proposed syntax: using StringDictionary<TValue> = System.Collections.Generic.Dictionary<String, TValue>; because there is no way for the compiler (other than convention) to tell if it should look up type TValue or if it is unbound. Thus the syntax in #116 is an obvious choice: using StringDictionary<> = System.Collections.Generic.Dictionary<string,>; EDIT: I take that back. Of course the compiler can match generic parameter type name from alias to generic parameter type name of aliased type. This will even allow reordering of type parameters. using MyDictionary<TValue, TKey> = System.Collections.Generic.Dictionary<TKey, TValue>; |
I had used |
But the proposed syntax is a reference to an existing type, not the declaration of a new type. In C#, the only way to reference an open generic type in code is by omitting the type arguments (e.g. By defining the support for aliasing open generic types using the same syntax as ¹ I'm ignoring XML documentation comments here, which have their own syntax. |
Why does aliasing need to be artificially limited by being intrinsically tied to This proposal is simply more intuitive and more functional. It solves the common use case of aliasing partially open generic types such as We're simply going to have to agree to disagree. That is why I submitted a separate proposal. |
Given:
What is |
However, |
👍 I also agree that this is an excellent idea. I've often wanted to do precisely what this proposal asks for. |
There is no way to get this out of file scope? |
@alrz The scope would, l imagine, be consistent with other using directives. |
I mean something like this, using class EmailAddress = String;
// or
class EmailAddress = String; so it'll be in scope in all files. |
@alrz Sounds like that should be a separate proposal entirely. I imagine it would be a compiler directive, as it is in VB.NET:
|
@HaloFour I wonder how F# is doing this for type abbreviations like |
@alrz The is no concept of aliases in the CLR. Every compiler that supports the notion does so in its own fashion and entirely internally. F# seems to treat |
@aluanhaddad It would also be useful to take it across assembly boundaries and use it without creating a named alias, neither of which are do-able with aliasing. |
@wizzardmr42 That sounds like an orthogonal feature. |
@aluanhaddad Sorry - just pointing out that wouldn't be a complete solution for everything discussed in #3281, which referenced this |
I was commenting specifically on the mention of the current limitations with type aliases. It was someone else who had suggested that type aliases could be an alternative workaround to the original proposer's problem. This proposal is only a modest extension of existing aliases in C# and does not touch on the subject of extending them beyond the current code file. @alrz has proposed #7451 to extend aliases throughout the current project using code notation. I personally prefer VB.NET's way of handling that, by using command line arguments to the compiler (exposed through the project configuration) to establish project-wide aliases. For something beyond the current project there could either be tooling to help configure multiple projects within a solution, or there would need to be a convention of embedding some kind of metadata in the assemblies to declare aliases. That concept seems very messy as it sounds like it would establish a second type system within the compiler that would be erased by compilation and ignored by the CLR. |
Sorry - I actually meant to post that on #3281, but it is worth pointing out here too that being able to reference existing types using a "typeof" keyword would solve some of the same problems that this would so may be worth looking at #3281 before implementing this (and #7715 which is a duplicate, but I gave more specific cases where it would be useful there). |
One immediate benefit of project-wide vs. solution-wide aliases is the possibilty of shared source files binding to different types according to the project they are being compiled against without having them poluted with conditional compiler directives. Atlthough that would erase the obiousness of the per-project semantics. |
@paulomorgano I didn't think of that! It would be a pleasant workaround for #7451 in case of need for solution-wide aliases. |
Hi All, The example that I deal with a lot is related to refactoring generic classes that inherit from other generic classes. Take this example below:
If I want to change
In order to get around that, I'll usually create a type that simply inherits from one of my generic parameters. For example:
When I do this, all I'm really doing is creating an alias for T that gets propagated down into child classes. In most cases, I really prefer that because I don't have to deal with giant generic definitions and it makes refactoring possible, however, the one downfall of doing things the way that I am is that I love a construct that would allow me to create a true alias for a type and pass that down into derived or other classes. For example, here is a thought:
|
@TonyValenti While that is certainly a scenario I would like to see supported, it seems like a perfect use case for a custom-refactoring, and not a language feature. This proposal is nicely focused and scoped (no pun intended), adding significant value while impacting little else in the language. That said, I think the scenario you mention is very compelling and I would find it very useful, but it could be a refactoring. That said, if it naturally falls out of this proposal, so much the better. |
The resemblance is eerie: https://github.com/apple/swift-evolution/blob/master/proposals/0048-generic-typealias.md typealias DictionaryOfStrings<T : Hashable> = Dictionary<T, String> using StringDictionary<TValue> = System.Collections.Generic.Dictionary<String, TValue>; |
Issue moved to dotnet/csharplang #1239 via ZenHub |
This is an alternative proposal to #116.
I propose the following changes to aliases to support generics:
* There's probably a better item in the spec for this.
The purpose of this proposal is to allow aliases to be defined for unbound or partially bound generic types where the alias is then treated as a generic type that must be closed at the point at which it is used.
For example the following is legal in C# today:
This expansion would permit the following:
The name of the generic type parameter can be anything. The arguments are matched by their position in the aliased type.
When consuming the alias the rules would apply the same as when consuming a generic type:
Arguments:
This syntax cannot be assembled from existing syntax within the specification thus requiring additional work.
This is true. Even though I provide a syntax above it is likely incorrect and the feature probably requires some new syntax. I believe that this is worth it for the functionality that the feature provides and I also feel that this syntax is more intuitive to the developer than the alternatives.
Requiring the developer to name the generic type arguments is confusing.
Naming generic type arguments is a very common task for anyone who has to write a generic type or generic method today. This should be somewhat second nature. This proposed syntax is very similar to the same syntax that would be required to define a new generic class with a generic subclass.
Requiring the developer to name the generic type argument requires more keystrokes.
This would require more keystrokes than simply using the existing unbound type syntax. However, the developer is not bound to using the same generic type parameter names as the type that is being aliased making the required number of additional keystrokes only one per generic type parameter. Given the common convention for generic type parameters is a single character, e.g.
T
, I don't think that this places an undue burden on the developer defining the alias nor any developer who must read and maintain that alias. It also represent a very small price to pay for the keystroke benefits that the feature would provide.Complications:
using MyList<T> = System.Collections.Generic.List<MyList<T>>;
.The rules for aliases today already solves this problem by not permitting an alias to refer to itself or another alias. If that weren't the case this scenario would already be problematic:
using MyList = System.Collections.Generic.List<MyList>;
2. The alias can represent a partially open generic type which is problematic if the developer attempts to obtain a
Type
instance from the alias viatypeof()
.This is true. Given the
StringDictionary<T>
alias defined above it would be a problem to attempt to obtain aType
reference usingtypeof(StringDictionary<>)
. In my opinion this could be solved in one of two possible ways:Make it illegal to use the unbound type definition of the alias. The expression
typeof(StringDictionary<>)
would be a compile-time error, however the expressiontypeof(StringDictionary<bool>)
would be valid and equivalent totypeof(Dictionary<String, bool>)
. This might be confusing if aliases to an unbound type were supported, e.g.typeof(MyList<>)
.Support partially open
Type
references. This requires a little more code generation but is perfectly legal:I am including this potential solution for the sake of argument. While being able to support syntax
typeof(StringDictionary<>)
would reduce the confusion for the developer I think that same developer would be more confused if the result is a partially open generic type.The text was updated successfully, but these errors were encountered: