Skip to content
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

New type aliases for long established types #12874

Closed
MrMatthewLayton opened this issue Aug 2, 2016 · 10 comments
Closed

New type aliases for long established types #12874

MrMatthewLayton opened this issue Aug 2, 2016 · 10 comments
Labels
Area-Language Design Resolution-Won't Fix A real bug, but Triage feels that the issue is not impactful enough to spend time on.

Comments

@MrMatthewLayton
Copy link

MrMatthewLayton commented Aug 2, 2016

Ever since C# 1.0 there have been built in aliases for several of the CTS compatible types (...and some non CTS compatible types)

For example

System.Int32 as int
System.Single as float
System.String as string

Suggestions 1

There is one known CTS compatible type that has no alias, which is System.IntPtr and I would like to know how feasible it would be to add an alias for this type to future versions of C#

For example

System.IntPtr as ptr or intptr

Suggestion 2

There are several types that are regularly used in C#, but are not CTS compatible, however it might be nice to have aliases for them anyway

For example

System.DateTime as date or datetime
System.Guid as guid
System.UIntPtr as uptr or uintptr

Please discuss.

@dsaf
Copy link

dsaf commented Aug 2, 2016

It would (also) be nice to be able to define assembly/namespace wide custom aliases #7451 (currently mislabeled as Discussion).

@dsaf
Copy link

dsaf commented Aug 2, 2016

Also related to #11993.

@theunrepentantgeek
Copy link

theunrepentantgeek commented Aug 2, 2016

While the idea has merit, there are some non-obvious fishhooks to consider.

For example, aliasing System.DateTime as date would be problematic since System.DateTimeOffset is preferred by many because of its timezone handling.

@MrMatthewLayton
Copy link
Author

MrMatthewLayton commented Aug 2, 2016

@theunrepentantgeek how about this..,

System.DateTime as date or datetime
System.DateTimeOffset as dateoffset or datetimeoffset (Possibly even just offset, but that seems ambiguous at best)

Perhaps this is becoming a little too convoluted.

@theunrepentantgeek
Copy link

theunrepentantgeek commented Aug 3, 2016

The thing that will probably kill this suggestion is that it would break existing code.

This code is valid under C#6 and earlier:

var date = DateTime.Now

But, type aliases aren't permitted as variable names, so this code is not permitted under C#6 and earlier:

var int = DateTime.Now;

If date became a valid type alias, then the first example will suddenly fail to compile.

@MrMatthewLayton
Copy link
Author

Having given some more thought to this...

One of the key difficulties I see students face when learning object oriented programming is being able to differentiate between the language itself, in terms of it's reserved words (keywords), semantics & syntax, and the framework itself; at a granular level, the type system, or the objects that the language is working with. Most, if-not-all C syntax/style languages seem to do this.

You know what...lets expand on that - even some mid-level developers don't fundamentally know the difference!

With regards to the aforementioned suggestion, rather than adding new type aliases to the language, it would actually be more appropriate to allow type aliases to be completely configurable throughout the language, source code, and development experience.

Imagine C# without the following keywords:

byte sbyte short ushort int uint long ulong float double decimal bool string char object null

Yes, you saw that correctly, null is in there too! Now the question is, how would you write an application without these keywords?

One (partial) solution would be to use the fully qualified type...

Instead of this...

int age = 32;
string name = "John Smith";

You could do this...

using System;
...
Int32 age = 32;
String name = "John Smith";

But, what happens when you need null? - since null is no longer a keyword, you can't do this...

Person p = null; // Syntax error, null is not a valid keyword.

However if I remember correctly, null actually refers to System.Null, which is implemented under the hood as a unary type (it only has one value, which is null) and is hidden away from the developer.

Therefore in this scenario, we as developers would need System.Null to become visible, so that we could do this...

using System;
...
Person p = Null; // System.Null

Since we no longer have any type aliases to work with, C# would require a way for these to be configurable within the scope of the application. Alternatively the runtime could automatically do this under the hood for backwards compatibility.

By default, the application would have a configuration file, which I have named "TypeDefs.cs"

global::define int as System.Int32;
global::define string as System.String;
global::define null as System.Null;

These definitions become global, that is, used throughout the application and cannot be overwritten once defined. Subsequent attempts to override a type definition would result in a compiler error. Roslyn code analysis could have additional analysers to nag people who deviate from the standard type definitions.

At the file level...

namespace Contoso.BusinessLogic.Models.Foo
{
    using System;
    define datetime as System.DateTime;

    class FooModel
    {
        public datetime CreatedDate { get; set; }
    }
}

In summary, this provides the following improvements to the language:

  • Provides a clear separation of language semantics and the type system.
  • Backwards compatible with existing code, using pre-defined global types (TypeDefs.cs) or done by the runtime under the hood.
  • Allows complete control over aliases in the type system.
  • Allows developers to define their own type aliases as part of a solution.
  • Can be tied into Roslyn code analysis.

Food for thought (syntax alternatives)

global::define datetime as System.DateTime;
global::define datetime = System.DateTime;
global::type datetime as System.DateTime;
global::type datetime = System.DateTime; //almost syntactically identical to TypeScript

Food for thought (C#7 nullable reference types proposal)

This feature might actually fit really well with the nullable reference type proposal.

[(https://github.com//issues/5032)]

Consider the following type definitions

define int as System.Int32; // Non-nullable by design...it's a struct!
define string as System.String // ...? guess what happens here!

Well, we've defined that stringis an alias for System.String, so, it MUST ALWAYS be System.String, and can't be null. If you want nullability, you could implement this the same way TypeScript does it.

define string as System.String | System.Null;

@HaloFour
Copy link

@series0ne

null is not an alias to any type, not in C# and not in the CLR. System.Null does not exist. Trying to use an alias to define null makes very little sense.

Type aliases already have a syntax with the using keyword.

Global type aliases have already been proposed and declined.

I don't see how aliases improve the non-nullable references problem. TypeScript can be much looser-and-faster with type definitions (and survive a breaking syntax change), but in C# (and the CLR) union types don't exist, and as mentioned above null isn't some other type, nor is it some sentinel object like it is in JavaScript.

@JesperTreetop
Copy link

JesperTreetop commented Aug 13, 2016

@series0ne: Maybe you are confusing null with void, which is the unmentionable struct type System.Void.

@MrMatthewLayton
Copy link
Author

@JesperTreetop correct!

@HaloFour having investigated this in ILSpy, I can see where I was wrong, it's not null I was thinking about, it's void

In essence then, null is a reserved word with unary value (it can only ever be null)

This would explain why this works...

typeof(void)

And this doesn't

typeof(null)

I understand your point about type aliases already having syntax with the using keyword...I guess this proposal would essentially allow two strains of aliasing...back to the drawing board.

@gafter
Copy link
Member

gafter commented Aug 17, 2016

We're so fond of this feature request, that we've retroactively added support to previous versions of our compilers. You can even select your own spelling for these types! To do so, place the following near the top of your source file:

using datetime = System.DateTime;
using intptr = System.IntPtr;
using guid = System.Guid;

We don't think we can possibly improve on that.

Just kidding. I agree with @theunrepentantgeek #12874 (comment)

@gafter gafter closed this as completed Aug 17, 2016
@gafter gafter added the Resolution-Won't Fix A real bug, but Triage feels that the issue is not impactful enough to spend time on. label Aug 17, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Language Design Resolution-Won't Fix A real bug, but Triage feels that the issue is not impactful enough to spend time on.
Projects
None yet
Development

No branches or pull requests

7 participants