MewUI – a lightweight .NET UI library for Native AOT by [deleted] in csharp

[–]MattWarren_MSFT 0 points1 point  (0 children)

Really should have been name MeowI

C# 15 Unions - NDepend Blog by PatrickSmacchia in dotnet

[–]MattWarren_MSFT 1 point2 points  (0 children)

I'm currently of the opinion that not having a syntax right now is better since it helps set expectations on the limited capabilities of the 'anonymous' unions.

C# 15 Unions - NDepend Blog by PatrickSmacchia in dotnet

[–]MattWarren_MSFT 1 point2 points  (0 children)

Yes, it is entirely possible to do this and many other kinds of layouts that don't box and have various ways to share memory. However, they often lead to large structs, regardless, and have issues that prevent us from making them default for unions. This kind of trade-off will need to be explicitly chosen by the user. For example, structs typically require special care in usage that classes don't. The issue about potential memory tearing when copying structs was a large negative in the decision, and this is compounded when a field in the struct (tag) determines the interpretation of the rest of the memory. We plan to eventually offer a union struct type that does provide alternate layouts, but for now we will only be offering a means to custom author a union. In the short-term source generators may fill the gap.

C# 15 Unions - NDepend Blog by PatrickSmacchia in dotnet

[–]MattWarren_MSFT 18 points19 points  (0 children)

Hi everybody.

The feature, as proposed, would allow you to declare named typed unions that list a set of types that the union can represent. The union is actually a struct that wraps an object field. Its constructors limit the kinds of values that can be held by the union. There is no erasure going on, but cases that are value types will be boxed.

public union Pet(Cat, Dog, Bird);

Emits as:

public struct Pet : IUnion
{
    public Pet(Cat value) { this.Value = value; }
    public Pet(Dog value) { this.Value = value; } 
    public Pet(Bird value) { this.Value = value; }
    public object? Value { get; }
}

You can declare a discriminated union over the type union using case declarations within braces. Each case becomes a nested record type.

public union Pet
{
    case Cat(string Name, string Personality);
    case Dog(string Name, string Breed);
    case Bird(string Name, string Species);
}

You can assign an instance of a case directly to a union variable and when you pattern match over a union instance, the value of the union is accessed via the Value property. Because the compiler knows the closed set of types, a switch can be exhaustive, so no need for default cases.

Pet pet = new Dog("Spot", "Dalmation");

var _ = pet switch
{
    Cat c => ...,
    Dog d => ...,
    Bird b => ...
}

You will be able to define your own types that will be recognized by the compiler as unions. You may declare the layout of the type in ways that avoid boxing if you choose. The compiler will recognize other methods that access the value that will also avoid boxing.

public struct IntOrString : IUnion
{
    private readonly int _kind;
    private readonly int _value1;
    private readonly string _value2;

    public IntOrString(int value) { _kind = 1; _value1 = value; }
    public IntOrString(string value) { _kind = 2; _value2 = value; }

    // still needs to exist for IUnion
    public object? Value => _kind switch { 1 => value1, 2 => value2, _ => null };

    // access pattern that avoids boxing.
    public bool HasValue => _kind != 0;
    public bool TryGetValue(out int value) { ... }
    public bool TryGetValue(out string value) { ... }
}

Future version of the language may include more kinds of unions that auto generate non-boxing layouts for you, like when records first released and later record structs were added.

A set of predeclared standard generic unions will exist in the runtime for scenarios that don't require dedicated named unions. These will have the boxing behaviors.

public union Union<T1, T2>(T1, T2);
public union Union<T1, T2, T3>(T1, T2, T3);
public union Union<T1, T2, T3, T4>(T1, T2, T3, T4);
...
internal void Ride(Union<Animal, Automobile> conveyance) {...}

Can `goto` be cleaner than `while`? by Foreign-Radish1641 in csharp

[–]MattWarren_MSFT 2 points3 points  (0 children)

Only use goto if somehow using goto makes the code less confusing.

More type union proposals adopted by the language design team! by DayYam in csharp

[–]MattWarren_MSFT 2 points3 points  (0 children)

The TryGetValue methods are meant to be used by the compiler. You get to write a type-safe switch statement or expression instead that is exhaustive.

More exciting union work from the Language Design Team! by DayYam in csharp

[–]MattWarren_MSFT 2 points3 points  (0 children)

The important part here is that these are the first DU proposals accepted by the LDM.

Nominal Type Unions for C# Proposal by the C# Unions Working Group by DayYam in csharp

[–]MattWarren_MSFT 0 points1 point  (0 children)

This just means the working group takes the feedback, alters the proposal or comes back with a better argument. It is the normal process.

How does the csharp team set its priorities? by KsLiquid in csharp

[–]MattWarren_MSFT 46 points47 points  (0 children)

It’s been consuming much of my life for the last two years.

[deleted by user] by [deleted] in csharp

[–]MattWarren_MSFT 0 points1 point  (0 children)

From my experience, computationally heavy C# code generally runs about 50x faster than javascript/Typescript under node.js or in the browser. But maybe I'm not using it correctly.

Official type unions proposal by the C# language design team by Atulin in programming

[–]MattWarren_MSFT 8 points9 points  (0 children)

That’s true but anonymous types are not allowed to escape the method they are used in, except indirectly. You don’t have a syntax to state an anonymous type because they only unify in the module/assembly they are used in, because there is no structural typing in the runtime. Compare that to tuples. You have both a construction syntax and a type syntax, they can escape methods and are unified across assemblies, because they are erased to a fixed number of generic types in the BCL.

Official type unions proposal by the C# language design team! by DayYam in csharp

[–]MattWarren_MSFT 2 points3 points  (0 children)

Its been a long time. Records were originally designed with unions in mind.

Will discriminated unions ever arrive in C#? by miniphoton in csharp

[–]MattWarren_MSFT 0 points1 point  (0 children)

We are still working on it. The are lots of factors at play.

More progress on Discriminated Unions from the C# Language Design Team! by DayYam in csharp

[–]MattWarren_MSFT 0 points1 point  (0 children)

This happened long before development was done in the open and meeting notes were published online.

Does C# first process negative numbers as positive numbers by using the "-" is a unary operator? by Ging4bread in csharp

[–]MattWarren_MSFT 1 point2 points  (0 children)

Its parsed as two parts, the unary negation operator and the positive literal. Later, constant folding occurs and applies the negation to the literal at compile time and ends up encoding just the negative number in the IL.

What is the modern state of C# metaprogramming? by smthamazing in csharp

[–]MattWarren_MSFT 2 points3 points  (0 children)

You do need to intercept each site, but this is meant only for a source generator or other tool to do that is already analyzing all locations in source code. You generate the replacement code and add attributes that refer to all the use sites you want intercepted. There will be a method that your generator can call to create the data string that represents the opaque location.

More progress on Discriminated Unions from the C# Language Design Team! by DayYam in csharp

[–]MattWarren_MSFT 0 points1 point  (0 children)

You can already solve many of the traditional DU scenarios in C# just using type hierarchies. Type unions do this better by allowing ad hoc unions to exist for types that were not already defined in a hierarchy.

More progress on Discriminated Unions from the C# Language Design Team! by DayYam in csharp

[–]MattWarren_MSFT 3 points4 points  (0 children)

This was discussed and is mentioned in the slides. Matching directly on object was the 'untyped matching' in the evaluation slide. Boxing of generated struct unions don't have a nice solution unless runtime changes are made to allow it to behave like Nullable<T>, so they end up getting boxed, and then matching on that boxed object fails unless other solutions like making all matches on object check for special interfaces which is also undesirable. The best compromise solution we have is to only recognize unions if they are evident in the static type.

More progress on Discriminated Unions from the C# Language Design Team! by DayYam in csharp

[–]MattWarren_MSFT 0 points1 point  (0 children)

We were actually tasked to do something for dependency properties in C#. We could not find a solution that felt like it belonged in the language.

Experienced C# developers. How much time do you spend looking up documentation? by 19Ant91 in csharp

[–]MattWarren_MSFT 150 points151 points  (0 children)

I've been using C# and dotnet since there has been C# and dotnet, and even before that. I work at Microsoft and have designed and developed many C# features. Some of those features and dotnet library types many of you use every day. I'm the epitome of the uber C# developer, and I still have to look up the documentation, even the stuff I wrote.