问题描述:

If I want a constructor that is only accessible from child classes I can use the protected key word in the constructor.

Now I want the opposite.

My child class should have an constructor that can be accessed by its base class but not from any other class.

Is this even possible?

This is my current code. the problem is that the child classes have a public constructor.

public abstract class BaseClass

{

public static BaseClass CreateInstance(DataTable dataTable)

{

return new Child1(dataTable);

}

public static BaseClass CreateInstance(DataSet dataSet)

{

return new Child2(dataSet);

}

}

public class Child1 : BaseClass

{

public Child1(DataTable dataTable)

{

}

}

public class Child2 : BaseClass

{

public Child2(DataSet dataSet)

{

}

}

网友答案:

I think you have two options:

  1. Make the child constructor internal. This means it will be accessible from all types in the same assembly, but that should be enough in most cases.
  2. Make the child classes nested in the base class:

    public abstract class BaseClass
    {
        public static BaseClass CreateInstance(DataTable dataTable)
        {
            return new Child1(dataTable);
        }
    
        private Child1 : BaseClass
        {
            public Child1(DataTable dataTable)
            {
            }
        }
    }
    

    This way, BaseClass can use the constructor, but no other outside type can do that (or even see the child class).

网友答案:

Answer to the question is "NO"

There is no such thing exists in the OOP that allow child class constructor to visible only to the Base Class of it...

网友答案:

I think I just solved it by myself. After reading svicks solution with nested classes, I thought why not use an protected nested class as an argument?

Nobody from outside is able to create an instance of Arg and the public contructors from my child classes can only be used by BaseClass which can create Arg<T> instances.

public abstract class BaseClass
{
    protected class Arg<T>
    {
        public T Value { get; set; }
        public Arg(T value) { this.Value = value; }
    }

    public static BaseClass CreateInstance(DataTable dataTable)
    {
        return new Child1(new Arg<DataTable>(dataTable));
    }

    public static BaseClass CreateInstance(DataSet dataSet)
    {
        return new Child2(new Arg<DataSet>(dataSet));
    }
}


public class Child1 : BaseClass
{
    public Child1(Arg<DataTable> arg) : this(arg.Value) { }
    private Child1(DataTable dataTable)
    {
    }
}

public class Child2 : BaseClass
{
    public Child2(Arg<DataSet> arg) : this(arg.Value) { }
    public Child2(DataSet dataSet)
    {
    }
}
网友答案:

One could enforce the desired behavior at run-time by having the base constructor accept a ref parameter, and do something like (not threadsafe):

private int myMagicCounter;

public DerivedClass makeDerived(whatever) // A factory method
{
  DerivedClass newThing;
  try
  {
    ... do whatever preparation
    newThing = new DerivedClass(ref myMagicCounter, whatever);
  }
  finally
  {
    ... do whatever cleanup
  }
  return newThing;
}

BaseClass(ref int magicCounter, whatever...)
{
  if (magicCounter != myMagicCounter)
    throw new InvalidOperationException();
  myMagicCounter++;
  if (magicCounter != myMagicCounter)
    throw new InvalidOperationException();
}

Note that it will be impossible for a derived class constructor call to get control without having done the factory method's preparation, or to return control to its caller without doing the factory method's cleanup. There will, however, be nothing to prevent the derived-class constructor from passing its partially-constructed instance to outside code which may do whatever it likes with it for an arbitrary amount of time before returning control to the factory method.

网友答案:

As Pranay Rana said, this is impossible. If you can clearly explain why you would want this, and why no other technique is possible, then maybe the Microsoft c# designteam is willing add this in a future version of C#.

However, the C# language (and many other OO languages have been around for many years without this possibility.

相关阅读:
Top