Replies: 38 comments 7 replies
-
So just to be clear, I could add a source file with the following contents: namespace Foo {
internal using Map<T> = System.Collections.Generic.Dictionary<string, T>;
} And have some other source file with the following contents: using Foo;
namespace Bar {
static class Program {
static void Main() {
var map = new Map<int>();
if (map is Dictionary<string, int>) Console.WriteLine("yay!");
}
}
} And the compiler will resolve the Also note that I used the fully-qualified type name to define the "alias" |
Beta Was this translation helpful? Give feedback.
-
Whatever we do here, I hope we don't block a future CLR improvement where I can declare a runtime type alias, enabling me to change the name of a type without breaking source or binary compatibility. |
Beta Was this translation helpful? Give feedback.
-
Here's the context. using System.Collections.Generic;
namespace Foo {
internal using Map<T> = Dictionary<string, T>;
} To make that work in the same level, RHS should consider preceding using directives, using System.Collections.Generic;
internal using Map<T> = Dictionary<string, T>; Which might be a breaking change (not if we only do that for internal aliases). |
Beta Was this translation helpful? Give feedback.
-
Once CLR support this, we can extend the set of allowed modifiers to |
Beta Was this translation helpful? Give feedback.
-
IIRC, currently the compiler requires fully-qualified type names in aliases in order to avoid potential circular references. How would you propose avoiding that issue with "internal aliases"? |
Beta Was this translation helpful? Give feedback.
-
Could you give an example? Supposedly the compiler can detect such cases as it does for base classes. |
Beta Was this translation helpful? Give feedback.
-
I think rather than redefining what |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
@playsomethingsaxman That allows moving a type between assemblies, which I have done, but there is no facility to typeforward a name change or namespace change. |
Beta Was this translation helpful? Give feedback.
-
Wouldn't |
Beta Was this translation helpful? Give feedback.
-
I think type parameters and user defined access modifiers look better with explicit aliasing syntax using some new keyword like public typealias StringKeyDictionary<T> = Dictionary<string, T>; And |
Beta Was this translation helpful? Give feedback.
-
I'd like this to have an additional
My proposed
Similarly:
While this code would cause a compile error:
This example of a database system is contrived and certainly a case where this isn't really a problem in practice, but it would be useful for zero-cost dimensional analysis.
Which could then be used like so for zero-cost dimensional unit constraints:
So this works:
But this won't:
Neither will this:
|
Beta Was this translation helpful? Give feedback.
-
How about allowing this inside generic classes? For example:
P.S. Although in my example you can just make derived classes, I've encountered many cases where derived classes are impossible (for example, you must accept/return externally declared interfaces with many type parameters). |
Beta Was this translation helpful? Give feedback.
-
Agreed, exactly what I need |
Beta Was this translation helpful? Give feedback.
-
You could emit metadata into the assembly, some sort of attribute which defines the aliases (type, string). Then
|
Beta Was this translation helpful? Give feedback.
-
There is currently no champion for this item, so the ldm is not prioritizing this in any way.
It's definitely not that simple :-) |
Beta Was this translation helpful? Give feedback.
-
Some things to consider in this space:
There are already proposals for the first two, but I think this is a better place to invest instead of extending For namespaces this would be really impactful for layered applications, e.g. in a web app you may have a domain model, api model and business model all with the same name. Using extern alias for each is even less convinient than repeating F# already supports this (I think only for types) and it's speced that these won't be accessible from outside of the assembly and that haven't been much of a problem so far. I suspect one reason for this to not get prioritized is that there's no immediate usecase in roslyn or corefx, but it's an absolute necessity in other kinds of applications. |
Beta Was this translation helpful? Give feedback.
-
So proposals useful for Roslyn or CoreFx are prioritized? Maybe that's natural. |
Beta Was this translation helpful? Give feedback.
-
@gulshan |
Beta Was this translation helpful? Give feedback.
-
I don't think this is true. Rather, I think that internal-only aliases is not the approach we want to take. For example, are these a compile-time only construct? If so, what happens to assemblies with IVT? The only logical answer is that they see the original type, not the alias. And if it's not a compile-time only construct, and somehow encoded in metadata, then it would be sad if you couldn't use these in a public interface. But then we have the question of whether aliases are identity-convertible to their underlying type. You might want that for a simple alias of a complicated generic type, but if you were creating a units library, for example, you might want your miles alias to not be identity-convertible to your kilometers alias. Plus, a metadata encoding would likely want runtime support, particularly for the opaque version. So, I don't think that the problem is not something that we want to solve. Rather, I think that we haven't found a proposal yet that we like, and no one on the ldt has sat down to make one either. |
Beta Was this translation helpful? Give feedback.
-
FWIW I think the introduction of DUs would make another use case for global aliases, for instance you may have a generic Result<T, E> and you'd want to define aliases for each kind of error:
I think that is how all Rust's result types are defined. |
Beta Was this translation helpful? Give feedback.
-
This has been my personal favorite feature request for a while. It would increase our team's productivity significantly, and we can't be the only ones. I already explained our case at Build Developer Day, but let me post it there too. Our system has many, many entities (over 200). It's common that their IDs are passed around as plain integers. There's been many cases where developer mixes IDs of different, similar sounding entities, let's say UserContact and UserConfig. So I got an idea to make strongly typed IDs for entities, to avoid mixing them. It's implemented as struct |
Beta Was this translation helpful? Give feedback.
-
@jukkahyv Let me just put a plug for my proposal #3046 here, which could be helpful for your specific case. It purposes to have generic types defined as |
Beta Was this translation helpful? Give feedback.
-
Plugging an already negatively-reviewed proposal probably isn't a good idea. Regarding the actual relevance of the proposal, |
Beta Was this translation helpful? Give feedback.
-
Actually, I forgot to mention one big point. By making it a single name (like UserContactId), it can be autocompleted with intellisense much faster than generic type + parameter. It sounds like a small thing, and it is, until you realize you're doing it 10 or 50 times per day. |
Beta Was this translation helpful? Give feedback.
-
And here I use F# type inference every day. 😃 |
Beta Was this translation helpful? Give feedback.
-
Imagine C# had aliases allowing this: public abstract class Base
{
public abstract alias Inner<T>;
}
public Generic<T> {}
public Impl : Base
{
public override alias Inner<T> = Generic<T>;
} Then HKT would become unnecessary as you could be able to emulate them using this technique: H<T> F<H<>, T>(H<T> h) => h; becomes class H
{
public abstract alias Inner<T>;
}
G.Inner<T> F<G, T>(G.Inner<T> h) where G : H => h; |
Beta Was this translation helpful? Give feedback.
This comment was marked as spam.
This comment was marked as spam.
-
I greatly agree with your suggestion, but I think it's subject for a different proposal. I would define For your proposal, I would suggest Also, this proposal don't require CLR changes (although can benefit from them) - even public aliases could be exposed as attributes, as already pointed out. But your proposal requires CLR changes, because otherwise the following code will result in wrong: type MyType = int;
// ...
object o = new MyType(5);
if (o is int)
{
Console.WriteLine("Oops, they should be different types.");
} Although now it's crossing my mind that it can be implemented by the compiler by new struct containing the type, and re-exposing all of its public members: struct MyType
{
int _Field;
// All int members
} This will have overhead, but since the JIT will optimize this away this should be fine. |
Beta Was this translation helpful? Give feedback.
-
Does there exist a hack or third-party solution for the simplest form of this: a global (per compilation unit) alias for a non-generic type, which only exists at compile-time? I can't find anything that's not hypothetical in this thread, in #7451, or on the web. |
Beta Was this translation helpful? Give feedback.
-
Ported from dotnet/roslyn#7451.
While using-alias-directive "introduces an identifier that serves as an alias for a namespace or type within the immediately enclosing compilation unit or namespace body", internal aliases can be referenced anywhere within a program.
Alternatively we could use
alias
ortype
, sinceinternal
carries some implications:InternalsVisibleTo
should work with internal aliases but it won't.internal
is "the default" modifier in a global or namespace context.However, with CLR support we could extend the set of allowed modifiers for a type alias in the future.
EDIT: Following
using static
perhapsusing internal
is a better choice here.Beta Was this translation helpful? Give feedback.
All reactions