-
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
Strongly-typed type aliases #58
Comments
I am also for
As for the syntax, I think something in-between the 2 you've mentioned is probably the best bet.
Syntactically it will look like an interface description, where the implementations come from the underlying type. A simple declaration of Semantically I think Explicit casts between The I think the point of The design goals for
I'm flexible on implementation details, but I think the above goals in that order should be considered. Some are at odds with each other, and in those cases I think the first goals should be given priority. |
If this was the case, wouldn't it mean that
I think it's a bad idea to have two ways to create a type, one of them validating and the other not, so this feature should not encourage that. This, along with some of your points, indicate it might make sense to allow only what you call |
Yes, you're absolutely right. From a syntactic sugar standpoint, it doesn't gain us much. However, my other interest in having such a language feature is in generating efficient runtime code. I'm happy to declare my In many ways this is similar to some of the motivations behind Some links of interest: |
Yes I agree that figuring out private explicit casts would be the preferred approach. Although since casts can be written to do anything (including doing validation) perhaps the solution is to just always cast and then you can put validation logic in the explicit cast? Not sure what best practice would be here. |
@rcook I think in terms of efficient code generation, something like .NET Native should fairly easily be able to remove any overhead (since it has limitations on reflection anyways, and reflection is the only place you should really be able to notice a difference in whether the type exists or not). |
I don't think you really want this to be just a compile time thing, if you do that then "strongly type" goes out of the window as soon as you cross the project/assembly boundary. You can simply make EmailAddress a The only trouble with using a |
Another problem by using a struct is obviously boxing. There is still plenty of framework code that you might call that knows nothing about an |
@mburbea What kind of framework code specifically do you have in mind? The only case I think think of are methods similar to |
Heck even simple things like |
We don't expect to do this. You can accomplish this using structs, and we expect source generators #5561 to make that less painful. |
@MadsTorgersen this is unfortunate (at least). How do you accomplish it with struct? Either I am missing something or you would have to constantly type something like Anyway, it is 2022 and working with primitive types (like long, int) was a pain years ago and it is pain still. This is because I cannot differentiate that this |
Wrap the primitive with a struct (or a record-struct).
Only if you actually want to work with the underlying value. But then you're losing the strong typing. The point of strong typign would be not have that happen, but to instead inforce you only use the actual strong type, while still benefiting from a small internal representation that would not leak out.
Just have a |
At the end of the day I have to.
I understand it. My point is, struct wrappers are not solution, they are merely workarounds. You have to type more, your code is bloated just because some feature is missing. If it was the case only single feature in given language is missing, fine, but there are much more and as the effect I constantly write code which I shouldn't. |
I don't get the distinction.
You're always going to have to type more. You need some way to define this new alias, and that means more code.
There should be no bloat. That's the point here. These are structs, so they have the exact size of the data they wrap. It's bloat free.
This is the feature though |
@CyrusNajmabadi you do understand the difference between one extra line and multiple/thousands of |
It's unclear why you need multiple/thousands of |
|
@macias I don't know what that code is meant to convey. It's also unclear why you're adding NodeIds or RoadIds. However, if that is something you intend to do in your domain, then that's fine. There's no reason you have to use .Value in thousands of places to do so. |
@CyrusNajmabadi could you give us an example on how you implement this with struct or any other way currently available in the language, with no need to write .Value or something like that? Don't forget about serialization - those aliases should serialize as if they were aliased types, not something like {"Value": 5} |
I'm not sure what you're asking for. What are three cases where you would need to write .Value? You're making the claim you would have thousands of these. I'm the one asking for examples as I don't get why that would be necessary.
Then write your serialization code to do that. |
I would love to see strongly-typed type aliases in the C# programming language. These would be roughly equivalent to types declared in Haskell using
newtype
. Such aliases would be very different from regular aliases declared usingusing
statements since the source-level type would ultimately be erased by the compiler. However, they would behave as distinct types from the original type during compilation time.I think this would be very helpful for dealing with easily abused types such as
string
. Here's an example using a hypothetical new language structure using thenewtype
keyword:This is purely syntactic sugar, however, and the compiler will emit all references to type
EmailAddress
as references toSystem.String
instead. Perhaps some additional metadata could be applied to arguments of these alias types to provide a hint to compilers about the original (source-level) type assigned to it. There are obviously many questions that arise. The main one, I think, is what to do about methods that are declared on the original type: if they are all projected onto this new "virtual" type, then we lose all advantages of this new type safety. I believe that the compiler should prohibit the developer from calling any of the original type's members on a reference to the alias type without inserting an explicit cast back to the underlying type. Such a cast would be purely syntactic and would not incur any runtime overhead.In traditional C# programming, the developer would most likely wrap a
string
inside anEmailAddress
wrapper class to ensure type safety and to curate access to the underlying string. My proposed language feature would enable the developer to more elegantly express certain concepts without bloating the code with wrapper classes. Importantly, it would also allow generation of extremely efficient code.More issues:
newtype
?Perhaps
newtype
could look more like the definition of aclass
orstruct
:The text was updated successfully, but these errors were encountered: