2

Browsing the class System.Dynamic.DynamicObject, I find it is concrete (not-abstract) class, but preventing from creating an instance of it directly by making its default constructor protected.

So what is the point of not making it just abstract with a public constructor ?

Clarification:

class Base1
{
    protected Base1() // protected constructor, concrete class
    {
    }
}
class Derived1 : Base1
{
    public Derived1() : base()
    {
    }
}

abstract class Base2
{
    public Base2() // public constructor, abstract class
    {
    }
}
class Derived2 : Base2
{
    public Derived2() : base()
    {
    }
}
  • that's a good question mate. I hope someone will answer that soon, because I'm interested to know that myself too ! At first, I was going to tell you that maybe it was because only children should have access to concrete objects but abstract classes should do the trick – Kevin Avignon Jun 10 '15 at 11:39
  • Well, it doesn't have any abstract methods. You only need to use the `abstract` keyword to enable abstract methods, so perhaps they simply only use `abstract` on abstract classes with abstract methods? – Luaan Jun 10 '15 at 11:39
  • C# fully permits you to declare `abstract` class without any `abstract` member –  Jun 10 '15 at 11:51
  • keyword `abstract` is not used to restrict access to constructor, I guess it's the main point. class is not abstract but author decided to restrict access – Daniil Grankin Jun 10 '15 at 12:42

2 Answers2

2

With a protected constructor this is possible:

public class MyClass
{
    protected MyClass() { }

    public static MyClass GetInstance()
    {
        return new MyClass();
    }
}    

public class MyDerivedClass : MyClass
{
}

public static void Main()
{
    var myInstance = MyClass.GetInstance();
    var myDerivedInstance = new MyDerivedClass();

    var constructor = typeof(MyClass).GetConstructor(
                BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public,
                null,
                Type.EmptyTypes,
                null);

    var instanceFromReflection = (MyClass) constructor.Invoke();
}

An abstract MyClass can't be instantiated neither by MyClass.GetInstance() (compiler error at return new MyClass();), nor by the reflection kind (runtime error System.MemberAccessException: Cannot create an instance of MyClass because it is an abstract class.)

abto
  • 1,583
  • 1
  • 12
  • 31
1

There is a comment that explains

    /// <summary>
    /// Enables derived types to initialize a new instance of the <see cref="T:System.Dynamic.DynamicObject"/> type.
    /// </summary>
    [__DynamicallyInvokable]
    [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
    protected DynamicObject()
    {
    }

it's used somewhere to create objects of type System.Dynamic.DynamicObject

Daniil Grankin
  • 3,841
  • 2
  • 29
  • 39
  • At first I thought "that's so stupid, obviously you can do that", but this may actually be the reason - if you need to pass a `DynamicObject` somewhere, but don't actually want any implementation (e.g. some kind of null-`DynamicObject`). Saves you the trouble of creating an unnecessary `class NullDynamicObject : DynamicObject {}`. – Luaan Jun 10 '15 at 11:42
  • @Luaan I think your comment should be good if it is an answer! –  Jun 10 '15 at 11:54
  • @Daniel Your answer is just the question itself, not adding any valuable information. –  Jun 10 '15 at 11:56
  • @Desolator I'm not agree . There is in question about preventing to create directly, and nothing about creating from derived classes, if you make class abstract you won't be able to do it anymore. – Daniil Grankin Jun 10 '15 at 12:01
  • I didn't understand? If I have an `abstract class` with `public` constructor (or even without declaring a constructor, just make it uses default constructor), I can do the same. (i.e. I cannot create directly too) –  Jun 10 '15 at 12:04
  • you can not do this 'new DynamicObject()' wherever in that case, but if it's not abstract class you can do it in method (for instance) of derived class from DynamicObject – Daniil Grankin Jun 10 '15 at 12:08
  • Hmmmm... But it prevent me too in derived class e.g. `class tmp : DynamicObject { public static DynamicObject MakeObj() { return new DynamicObject(); } }` causes compilation error –  Jun 10 '15 at 12:13
  • point is to allow to create wrappers with DynamicObject, WrapperObject : DynamicObject – Daniil Grankin Jun 10 '15 at 12:18
  • sure, because your method static – Daniil Grankin Jun 10 '15 at 12:19
  • I was wrong about methods, but you can do this `class Tmp : DynamicObject { public Tmp() : base() { } }` it's redundant but it allows to understand why it's needed – Daniil Grankin Jun 10 '15 at 12:25
  • And again I can make the same behavior with this `abstract class Tmp { public Tmp() { } } class Tmp2 : Tmp { public Tmp2() : base() { } }` :-) :-) –  Jun 10 '15 at 12:27
  • can you create instance of abstract class in MSIL? – Daniil Grankin Jun 10 '15 at 12:30
  • or invoke constructor via reflection? – Daniil Grankin Jun 10 '15 at 12:31
  • @DanielGrankin I think any method can be invoked by reflection, unless it has SecurityCriticalAttribute, see http://stackoverflow.com/questions/135443/how-do-i-use-reflection-to-invoke-a-private-method –  Jun 10 '15 at 12:38
  • @Desolator but it doesn't allow you to create instance of abstract class? – Daniil Grankin Jun 10 '15 at 12:39
  • It does allow. see http://stackoverflow.com/questions/7191402/access-to-properties-of-abstract-class-with-reflection (unless the invoked method itself is abstract) –  Jun 10 '15 at 12:42
  • I'm not about invocation it, you can try invoke method which even doesn't exist. I'm about creation object. It can be used in runtime but it's not allowed to do directly. – Daniil Grankin Jun 10 '15 at 12:45