Newbie question about casted conversions...

Feb 11 2007 9:14 PM
Hi all, I'm pretty new to C#, but I've been trying to figure out the logic behind my problem for a couple of days now. The documentation I've read all makes sense, but I can't find anything about this particular circumstance/problem that I can identify. And actually, I'm not even sure what this sort of conversion technique is called, but it seems like an explicit conversion of a base class to a derived class of that base class... anyway, it doesn't work and I'm stumped, but I know I'm missing something really simple.
using System;
using System.Net;
using System.Net.Sockets;

namespace CastingTest {
	class NewSocketClass : Socket {
		string selfName;

		public NewSocketClass( AddressFamily af, SocketType st, ProtocolType pt ) : base( af, st, pt ) {
			selfName = "Generic";
			Console.WriteLine( "{0} constructed.", selfName );
		}

		public NewSocketClass( AddressFamily af, SocketType st, ProtocolType pt, string name ) : base( af, st, pt ) {
			selfName = name;
			Console.WriteLine( "{0} constructed.", selfName );
		}

		public void HelloWorld() {
			Console.WriteLine( "Hello, {0}!", selfName );
		}
	}

	class CastMain {
		public static void Main() {
			NewSocketClass s = new NewSocketClass( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp, "Listener" );
			s.Bind( new IPEndPoint( IPAddress.Loopback, 8090 ) );
			s.Listen( 10 );
			s.HelloWorld();

			NewSocketClass i = (NewSocketClass)s.Accept(); <-- Error: Cannot cast from source type to destination type.
			i.HelloWorld();
		}
	}
}
-- I should mention I've also tried simply declaring operator handlers for the conversions, and avoiding the derive altogether:
using System;
using System.Net;
using System.Net.Sockets;

namespace CastingTest {
	class NewSocketClass {
		string selfName;
		Socket sock = null;

		public NewSocketClass( Socket s ) : this( s.AddressFamily, s.SocketType, s.ProtocolType ) {
			this.sock = s;
		}

		public NewSocketClass( AddressFamily af, SocketType st, ProtocolType pt ) {
			selfName = "Generic";
			if( this.sock == null )
				this.sock = new Socket( af, st, pt );
			Console.WriteLine( "{0} constructed.", selfName );
		}

		public NewSocketClass( AddressFamily af, SocketType st, ProtocolType pt, string name ) : this( af, st, pt ) {
			selfName = name;
			Console.WriteLine( "{0} constructed.", selfName );
		}

		public static implicit operator Socket( NewSocketClass rvalue ) {
			return rvalue.sock;
		}
		public static implicit operator NewSocketClass( Socket rvalue ) {
			return new NewSocketClass( rvalue );
		}

		public void HelloWorld() {
			Console.WriteLine( "Hello, {0}!", selfName );
		}
	}

	class CastMain {
		public static void Main() {
			NewSocketClass s = new NewSocketClass( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp, "Listener" );
			((Socket)s).Bind( new IPEndPoint( IPAddress.Loopback, 8090 ) );
			((Socket)s).Listen( 10 );
			s.HelloWorld();

			NewSocketClass i = (NewSocketClass)((Socket)s).Accept();
			i.HelloWorld();
		}
	}
}
And this all works great, until I attempt to select on the resulting sockets, which results in:
Unhandled Exception: System.InvalidCastException: Cannot cast from source type to destination type.
  at System.Net.Sockets.Socket.AddSockets (System.Collections.ArrayList sockets, IList list, System.String name) [0x00000]
  at System.Net.Sockets.Socket.Select (IList checkRead, IList checkWrite, IList checkError, Int32 microSeconds) [0x00000]
and a clearer version (from MS.Net):
 Unhandled Exception: System.ArgumentException: The operation is not allowed on objects of type Valstream.VSListener. Use only objects of type System.Net.Sockets.Socket.
 Parameter name: socketList
    at System.Net.Sockets.Socket.SocketListToFileDescriptorSet(IList socketList)
    at System.Net.Sockets.Socket.Select(IList checkRead, IList checkWrite, IList checkError, Int32 microSeconds)
    at Valstream.VSMain.mainLoop()
    at Valstream.VSMain.Main()