Skip to content

Exception types for System.Net.Connections, Part 2 #40451

@scalablecory

Description

@scalablecory

We previously approved the following API in #39941:

namespace System.IO
{
    public class NetworkException : IOException
    {
        public static NetworkException Create(NetworkError error, Exception innerException = null, string message = null);
        protected NetworkException(NetworkError error, Exception innerException = null, string message = null);
        // serialization constructor as usual

        public NetworkError NetworkError { get; }
    }

    public enum NetworkError
    {
        Unknown,

        AddressInUse,       // SocketError.AddressAlreadyInUse
        InvalidAddress,     // SocketError.AddressFamilyNotSupported, SocketError.AddressNotAvailable, etc
        ConnectionRefused,  // SocketError.ConnectionRefused
        HostNotFound,       // SocketError.HostNotFound, SocketError.HostUnreachable, etc

        ConnectionAborted,
        ConnectionReset,
    }
}

With the understanding that we would create additional ConnectionResetException, ConnectionAbortedException, etc. and the factory would be updated over time to throw these more derived exceptions as we see fit to add them.

However, there are some changes identified post-review and during implementation that we'd like to discuss with API review:

  • @stephentoub, who was unable to attend API review for original issue, strongly believes creating additional derived exception types is a mistake and that we should embrace using exception filters for this.
  • @stephentoub called out that exception ctors typically have "message" first. We'd like to reorder and possibly add a second messageless ctor.
  • We put the API proposal in the wrong namespace. Moving to System.Net.
  • We need to add an OperationAborted error.
  • We should consider renaming AddressInUse and InvalidAddress to EndPointInUse and InvalidEndPoint -- "address" comes from the native API struct sockaddr, but our APIs do not actually use this term anywhere.

New proposal with modifications:

namespace System.Net
{
    public class NetworkException : IOException
    {
        public NetworkException(string message, NetworkError error, Exception innerException = null);

        // to enable pulling out standard messages? otherwise make message nullable in above ctor.
        public NetworkException(NetworkError error, Exception innerException = null);

        // serialization constructor as usual

        public NetworkError NetworkError { get; }
    }

    public enum NetworkError
    {
        Unknown,

        EndPointInUse,      // SocketError.AddressAlreadyInUse
        InvalidEndPoint,    // SocketError.AddressFamilyNotSupported, SocketError.AddressNotAvailable
        HostNotFound,       // SocketError.HostNotFound

        ConnectionRefused,  // SocketError.ConnectionRefused
        ConnectionAborted,  // SocketError.ConnectionAborted
        ConnectionReset,    // SocketError.ConnectionReset

        OperationAborted    // SocketError.OperationAborted
    }
}

Old usage

try
{
   throw NetworkException.Create(NetworkError.ConnectionReset);
}
catch(ConnectionResetException ex)
{
   // ...
}
catch(NetworkException ex) when(ex.NetworkError == ConnectionAborted || ex.NetworkError == OperationAborted)
{
  // ...
}

New usage

try
{
   throw new NetworkException(NetworkError.ConnectionReset);
}
catch(NetworkException ex) when(ex.NetworkError == NetworkError.ConnectionReset)
{
   // ...
}
catch(NetworkException ex) when(ex.NetworkError == ConnectionAborted || ex.NetworkError == OperationAborted)
{
  // ...
}

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions