Currently the build targets defines this via:
Condition="'$(TargetFramework)' == 'netcoreapp3.0' or '$(TargetFramework)' == 'netstandard2.1' or '$(TargetFramework)' == 'netstandard2.0'"
However, the Microsoft.Bcl.AsyncInterfaces package provides these for other TFMs (preview, waiting on .NET Core 3). If the APIs aren't unified, it is going to cause confusion for consumers, especially if they take transitive dependencies via any path that gives them both Microsoft.Bcl.AsyncInterfaces and System.Interactive.Async on any of the impacted TFMs.
Ultimately, having two sources of truth for these APIs is just a disaster for consumers. The extern alias hack exists, but is a pain to explain to users - who expect install-package to just work.
I would argue that Microsoft.Bcl.AsyncInterfaces is a more "official" source of truth than System.Interactive.Async (despite System.* vs Microsoft.*), and thus System.Interactive.Async must yield.
To repeat my analysis from here, the most likely outcome is:
- .NET Standard 2.1: type-forward to
System.Runtime
- .NET Core 3.0 - type-forward to
System.Runtime
- .NET Standard 2.0: type-forward to
Microsoft.Bcl.AsyncInterfaces
- (new TFM) .NET Framework 4.6.1: type-forward to
Microsoft.Bcl.AsyncInterfaces
- .NET Framework 4.6: define locally (but: correctly)
- .NET Framework 4.5: define locally (but: correctly)
- .NET Standard 1.3: define locally (but: correctly)
- .NET Standard 1.0: define locally (but: correctly)
(with a slightly simpler setup possible if we can collectively convince Microsoft to not omit any TFMs that System.Interactive.Async targets)
There is a knowledge gap (for me) here about what happens if MonoTouch1.0, for example, targets both (directly or indirectly); there is an explicit TFM for this in Microsoft.Bcl.AsyncInterfaces, but if "reactive" ends up providing the .NET Standard 1.0 or .NET Standard 1.3 build: the problem is back. If that is the case, I would say that it provides grounds for either:
- we lean on
Microsoft.Bcl.AsyncInterfaces to provide net46, net45, netstandard1.0 and netstandard1.3 TFMs, and remove the interfaces completely from System.Interactive.Async
- "reactive" should provide explicit TFMs for everything that
Microsoft.Bcl.AsyncInterfaces provides TFMs for (type-forwarding to Microsoft.Bcl.AsyncInterfaces), to ensure no danger zones
My preferred option is "1", and IMO the risk of customer/consumer impact by continuing to have multiple definitions should be a fair battering ram for adding them. That would allow the cleaner:
- .NET Standard 2.1: type-forward to
System.Runtime
- .NET Core 3.0 - type-forward to
System.Runtime
- .NET Standard 2.0: type-forward to
Microsoft.Bcl.AsyncInterfaces
- .NET Framework 4.6: type-forward to
Microsoft.Bcl.AsyncInterfaces
- .NET Framework 4.5: type-forward to
Microsoft.Bcl.AsyncInterfaces
- .NET Standard 1.3: type-forward to
Microsoft.Bcl.AsyncInterfaces
- .NET Standard 1.0: type-forward to
Microsoft.Bcl.AsyncInterfaces
which doesn't have any danger zones for transitives, since all "reactive" TFMs are provided for by the "official" sources.
Happy to try and help with a PR on the local changes if you think this unification is the way to go.
Currently the build targets defines this via:
However, the
Microsoft.Bcl.AsyncInterfacespackage provides these for other TFMs (preview, waiting on .NET Core 3). If the APIs aren't unified, it is going to cause confusion for consumers, especially if they take transitive dependencies via any path that gives them bothMicrosoft.Bcl.AsyncInterfacesandSystem.Interactive.Asyncon any of the impacted TFMs.Ultimately, having two sources of truth for these APIs is just a disaster for consumers. The
extern aliashack exists, but is a pain to explain to users - who expectinstall-packageto just work.I would argue that
Microsoft.Bcl.AsyncInterfacesis a more "official" source of truth thanSystem.Interactive.Async(despiteSystem.*vsMicrosoft.*), and thusSystem.Interactive.Asyncmustyield.To repeat my analysis from here, the most likely outcome is:
System.RuntimeSystem.RuntimeMicrosoft.Bcl.AsyncInterfacesMicrosoft.Bcl.AsyncInterfaces(with a slightly simpler setup possible if we can collectively convince Microsoft to not omit any TFMs that
System.Interactive.Asynctargets)There is a knowledge gap (for me) here about what happens if
MonoTouch1.0, for example, targets both (directly or indirectly); there is an explicit TFM for this inMicrosoft.Bcl.AsyncInterfaces, but if "reactive" ends up providing the .NET Standard 1.0 or .NET Standard 1.3 build: the problem is back. If that is the case, I would say that it provides grounds for either:Microsoft.Bcl.AsyncInterfacesto provide net46, net45, netstandard1.0 and netstandard1.3 TFMs, and remove the interfaces completely fromSystem.Interactive.AsyncMicrosoft.Bcl.AsyncInterfacesprovides TFMs for (type-forwarding toMicrosoft.Bcl.AsyncInterfaces), to ensure no danger zonesMy preferred option is "1", and IMO the risk of customer/consumer impact by continuing to have multiple definitions should be a fair battering ram for adding them. That would allow the cleaner:
System.RuntimeSystem.RuntimeMicrosoft.Bcl.AsyncInterfacesMicrosoft.Bcl.AsyncInterfacesMicrosoft.Bcl.AsyncInterfacesMicrosoft.Bcl.AsyncInterfacesMicrosoft.Bcl.AsyncInterfaceswhich doesn't have any danger zones for transitives, since all "reactive" TFMs are provided for by the "official" sources.
Happy to try and help with a PR on the local changes if you think this unification is the way to go.