We tend to code defensively and not make things public that don't need to be. In our edtFTPnet/Express and edtFTPnet/PRO products we do derive from FTPClient exactly as it is in edFTPnet.
I think it's fine not to make everything public but not to make them protected? IMO, that's unnecessarily restricting the developer who needs to extend the class and add functionality. FTPClient is pretty much locked down and meaningful extensibility isn't really supported. Without access to control nor CheckConnnection, to give two examples, there isn't much a descendant class can do. Take for example my reply to the post on exception handling. There is simply no easy way to implement exception handling in one central location even though that location, control.SendCommand, exists. It could be handled in two different ways.
1. Make the assignment of the control member available to the descendants of FTPClient so they could instantiate their own version of FTPControlSocket.
2. Create a virtual method on FTPClient called SendCommand which simply calls command.SendCommand.
My preference would be to have both that way exception handling can be added quickly and easily in addition, anyone who needs finer control over the FTPControlSocket has that as well. Either option would allow a descendant class to handle exceptions for all FTP calls in one location.
However there's no harm in making FTPReply public and we've now done so in our codebase - so the next version of edtFTPnet will have this.
Note that an interface of FTP methods already exists - IFileTransferClient.
Good to hear. Did you also make the constructors public?
In my review of the use of the internal keyword in this framework it seems overused. Restricting so much code to the edtFTP assembly seems unreasonable and reduces the usability of the framework overall.