Зачем все усложнять, когда вам не нужно?
Так как вы не инкапсулируете какие-либо неуправляемые ресурсы, вам не нужно все это копаться с финализацией. И ваши классы являются внутренними, что говорит о том, что вы управляете иерархией наследования в вашей собственной сборке.
Итак, прямой подход будет:
internal class FooBase : IDisposable
{
Socket baseSocket;
private void SendNormalShutdown()
{
// ...
}
private bool _disposed = false;
public virtual void Dispose()
{
if (!_disposed)
{
SendNormalShutdown();
baseSocket.Close();
_disposed = true;
}
}
}
internal class Foo : FooBase
{
Socket extraSocket;
private bool _disposed = false;
public override void Dispose()
{
if (!_disposed)
{
extraSocket.Close();
_disposed = true;
}
base.Dispose();
}
}
Даже если у вас есть неуправляемые ресурсы, я бы сказал, что вам гораздо лучше инкапсулировать их в их собственный одноразовый класс и использовать их так же, как и любые другие одноразовые; так же просто, как и код выше.