MicrosoftDocs / windows-dev-docs

Conceptual and overview content for developing Windows apps
Creative Commons Attribution 4.0 International
691 stars 1.2k forks source link

WinRT IComparable for API authoring #1392

Closed sichbo closed 5 years ago

sichbo commented 5 years ago

An important part of composing public APIs is that value types should be able to sort or compare in an expected and standard way. Under the CLI we have System.IComparable for that job but I'm not seeing any kind of analogue under the Windows.Platform namespace.

Can we get some guidance on whether or not it's possible for API authors to have their projected types implement System.IComparable when referenced by a .NET project? There's some nifty voodoo going on when it turns Windows.Foundation.Collections.IVector into System.Collections.Generic.List on the .NET side. Maybe a new Windows.Platform.IComparable to System.IComparable translator could be a thing 😉.


Document Details

⚠ Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

stevewhims commented 5 years ago

Acknowledging receipt! It's on my TODO list. :)

ginami commented 5 years ago

(Sorry about the close and reopen...we're doing some testing on our issues list!)

stevewhims commented 5 years ago

Hi, @sichbo, I've asked around internally for advice here. I don't see any way of projecting System.IComparable from a WinRT API that a developer is authoring (in this case, as you say, the scenario being that you want a generic contained to be able to sort your custom value type, for example). I'm not sure what further I can offer since this isn't directly an issue with this particular topic, nor do I have the info at hand to add to the topic.

I know that this is not immediately helpful to this question, and I apologize, but I can only offer the links I already shared a while ago for other avenues of exploration you could take as options. Those are (just for completeness): The Windows developer feedback site to file a product bug. For Visual Studio issues, the Visual Studio User Voice feedback website, or the Developer Community. And, finally, Microsoft Support. But this question feels like, if anything, a gap rather than an actual bug (as we said, bugs are refunded).

I'll leave this open, and see what you think about closing it.

Thanks! ~Steve

sichbo commented 5 years ago

Thanks for that Steve. Yeah it's just a gap. I'm hitting up against possibly another gap as I go along :) Instead of opening yet another question maybe you might be able to quickly confirm something, as I'm not sure if this is a missing feature or just something not quite documented yet.

Are we able at all to define a value type that contains operators, utility properties and functions for manipulating a lightweight struct? Intuitively I want to be able to go:

struct Timecode {

    Int64 Ticks;
    Double FramesPerSecond;

    //
    // Then all the bits and pieces that actually 
    // make this Value type useful :)
    //
    Timecode();
    Timecode(Int64 ticks);
    Timecode(Int64 ticks, Double fps);
    Timecode(Int32 days, Int32 hours, Int32 minutes, Int32 seconds, Int32 frames, Double fps);
    Timecode(Int32 days, Int32 hours, Int32 minutes, Int32 seconds, Int32 milliseconds);

    Timecode operator +(Timecode v);
    Timecode operator -(Timecode v);
    Timecode operator +(Int64 v);
    Timecode operator -(Int64 v);
    Timecode operator ==(Timecode v);
    Timecode operator !=(Timecode v);

    Int32 Days{ get; };
    Int32 Hours{ get; };
    Int32 Minutes{ get; };
    Int32 Seconds{ get; };
    Int32 Milliseconds{ get; };
    Int32 Frames{ get; };
    Double TotalDays{ get; };
    Double TotalHours{ get; };
    Double TotalMilliseconds{ get; };
    Double TotalMinutes{ get; };
    Double TotalSeconds{ get; };
    Int64 TotalFrames{ get; };

    Timecode SetValueFromAbsoluteFrameNumber(Int64 frameNumber);
    Timecode SetValueUsingMilliseconds(Int32 days, Int32 hours, Int32 minutes, Int32 seconds, Int32 milliseconds);
    Timecode SetValueUsingFrames(Int32 days, Int32 hours, Int32 minutes, Int32 seconds, Int32 frame);
};

A heavy refcounted runtimeclass can almost do the job, but performance is a concern here. In this case it's part of a cross platform (WinRT + Native Linux C++17/gcc + .NET CLI + .NET Core) media library where value Timecode gets tossed around hundreds of times per second amongst various moving pieces. I'm trying to keep API feature parity across all 4x project types, and so far WinRT's the only one not playing ball. Is there something akin to a runtimestruct? 🤔

If a struct with functions isn't possible, is there a secret syntax to get operators working on runtimeclasses? maybe if we name functions op_Add or op_Subtract etc they'd magically work under C#?

Even if there was some way to manually "by hand" extend the ABI code, that would be helpful.

stevewhims commented 5 years ago

Not operators. But you should be able to replace those with a function, and then you should be able to do what you illustrate there. Btw, we recently published a couple of relevant documents, and the part about operator overloading is here: https://docs.microsoft.com/uwp/winrt-cref/winrt-type-system#interface-members, if you look in that section for the heading "Operator overloading". There's a lot of interesting stuff in that topic. :)

As for the idea of "runtimestruct", that'd be covered by the WinRT struct: https://docs.microsoft.com/uwp/winrt-cref/winrt-type-system#structs. Note the limitations there, such as not being able to make them generic.

And, since you're building a library, I don't know whether you've heard of xlang, nor whether it could help you: https://github.com/Microsoft/xlang.

sichbo commented 5 years ago

Thanks, Steve - there's a lot of good info on that new page.

I'm sure there was a reason and it's unfortunate that "methods may not be named using the special operator names". Thanks for confirming the feature gap. Will close this up ;)