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

Move SocketTaskExtensions methods to Socket class itself #43901

Closed
geoffkizer opened this issue Oct 27, 2020 · 7 comments · Fixed by #45083
Closed

Move SocketTaskExtensions methods to Socket class itself #43901

geoffkizer opened this issue Oct 27, 2020 · 7 comments · Fixed by #45083
Assignees
Labels
api-approved API was approved in API review, it can be implemented area-System.Net.Sockets help wanted [up-for-grabs] Good issue for external contributors
Milestone

Comments

@geoffkizer
Copy link
Contributor

Background and Motivation

For historical reasons, all of the Task-based APIs on Socket are defined as extension methods in SocketTaskExtensions.

We should move these methods to Socket itself, and mark the existing extension methods in SocketTaskExtensions as [EditorBrowsable(EditorBrowsableState.Never)].

Proposed API

namespace System.Net.Sockets
{
    public partial class Socket
    {
        // Existing SocketTaskExtensions APIs, converted to instance methods

        public Task<Socket> AcceptAsync();
        public Task<Socket> AcceptAsync(Socket? acceptSocket);

        public Task ConnectAsync(EndPoint remoteEP);
        public ValueTask ConnectAsync(EndPoint remoteEP, CancellationToken cancellationToken);
        public Task ConnectAsync(IPAddress address, int port);
        public ValueTask ConnectAsync(IPAddress address, int port, CancellationToken cancellationToken);
        public Task ConnectAsync(IPAddress[] addresses, int port);
        public ValueTask ConnectAsync(IPAddress[] addresses, int port, CancellationToken cancellationToken);
        public Task ConnectAsync(string host, int port);
        public ValueTask ConnectAsync(string host, int port, CancellationToken cancellationToken);

        public Task<int> ReceiveAsync(ArraySegment<byte> buffer, SocketFlags socketFlags);
        public ValueTask<int> ReceiveAsync(Memory<byte> buffer, SocketFlags socketFlags, CancellationToken cancellationToken = default);
        public Task<int> ReceiveAsync(IList<ArraySegment<byte>> buffers, SocketFlags socketFlags);
        public Task<SocketReceiveFromResult> ReceiveFromAsync(ArraySegment<byte> buffer, SocketFlags socketFlags, EndPoint remoteEndPoint);
        public Task<SocketReceiveMessageFromResult> ReceiveMessageFromAsync(ArraySegment<byte> buffer, SocketFlags socketFlags, EndPoint remoteEndPoint);

        public Task<int> SendAsync(ArraySegment<byte> buffer, SocketFlags socketFlags);
        public ValueTask<int> SendAsync(ReadOnlyMemory<byte> buffer, SocketFlags socketFlags, CancellationToken cancellationToken = default);
        public Task<int> SendAsync(IList<ArraySegment<byte>> buffers, SocketFlags socketFlags);
        public Task<int> SendToAsync(ArraySegment<byte> buffer, SocketFlags socketFlags, EndPoint remoteEP);
    }
}

Note this change should apply to the following planned 6.0 APIs as well, which have already been approved as new extension methods on SocketTaskExtensions.

#1608
#42591
#33418

@geoffkizer geoffkizer added area-System.Net.Sockets api-ready-for-review API is ready for review, it is NOT ready for implementation labels Oct 27, 2020
@geoffkizer geoffkizer added this to the 6.0.0 milestone Oct 27, 2020
@ghost
Copy link

ghost commented Oct 27, 2020

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

@gfoidl
Copy link
Member

gfoidl commented Nov 6, 2020

A question on file-organisation. Add these to Socket.cs or a new partial class file (as Socket.cs is already huge)? Or to Socket.Tasks.cs?

@geoffkizer
Copy link
Contributor Author

In most cases this is probably just making the existing internal APIs in Socket.Tasks.cs public, as the stuff in SocketTaskExtensions.cs is already just calling directly into those methods.

@bartonjs
Copy link
Member

bartonjs commented Nov 10, 2020

Video

Looks good as proposed

  • Copy all members on SocketTaskExtensions to instance methods on Socket (removing the this parameter)
  • Mark existing members as EditorBrowsable(Never)
  • Remove any members on SocketTaskExtensions that have been introduced for .NET 6. Be nimble with regard to approved, but not-implemented ones.

@bartonjs bartonjs added api-approved API was approved in API review, it can be implemented and removed api-ready-for-review API is ready for review, it is NOT ready for implementation labels Nov 10, 2020
@geoffkizer geoffkizer added the help wanted [up-for-grabs] Good issue for external contributors label Nov 10, 2020
@davidfowl
Copy link
Member

Any reason to move the ArraySegment ones?

@geoffkizer
Copy link
Contributor Author

Any reason to move the ArraySegment ones?

Mostly just consistency. I don't think there's any harm in it, is there?

@stephentoub
Copy link
Member

stephentoub commented Nov 22, 2020

Mostly just consistency. I don't think there's any harm in it, is there?

On the contrary, I expect we'll find it's otherwise a breaking change. Imagine code like:

ArraySegment<byte> segment = ...;
Task<int> t = socket.ReceiveAsync(segment, SocketFlags.None);

With both the Task<int> ReceiveAsync(ArraySegment<byte>, ...) and ValueTask<int> ReceiveAsync(Memory<byte>, ...) overloads as extensions, the above code will bind to the ReceiveAsync that accepts an ArraySegment<byte>. However, if just the Memory<byte>-based overload "moves" to be an instance method, with ArraySegment<byte> implicitly convertible to Memory<byte>, the compiler will then bind to the instance method, at which point the ValueTask<int> it returns will fail to cast to the Task<int> to which it's being assigned, and compilation will fail. If, however, both the ArraySegment<byte> and Memory<byte> overloads are added as instance methods, then the compiler will prefer the ArraySegment<byte> instance method, and things will continue to compile.

Someone can check me on that, but I'm pretty sure that's how things would play out. Yay complexities of overload resolution.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
api-approved API was approved in API review, it can be implemented area-System.Net.Sockets help wanted [up-for-grabs] Good issue for external contributors
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants