30

I've got a (poorly written) base class that I want to wrap in a proxy object. The base class resembles the following:

public class BaseClass : SomeOtherBase 
{
   public BaseClass() {}

   public BaseClass(int someValue) {}

   //...more code, not important here
}

and, my proxy resembles:

public BaseClassProxy : BaseClass
{
  public BaseClassProxy(bool fakeOut){}
}

Without the "fakeOut" constructor, the base constructor is expected to be called. However, with it, I expected it to not be called. Either way, I either need a way to not call any base class constructors, or some other way to effectively proxy this (evil) class.

Jakub Šturc
  • 35,201
  • 25
  • 90
  • 110
casademora
  • 67,775
  • 17
  • 69
  • 78
  • `public BaseClass() { if ( GetType() != typeof(BaseClass) ) return; ... }` –  Dec 11 '20 at 23:13

13 Answers13

68

There is a way to create an object without calling any instance constructors.

Before you proceed, be very sure you want to do it this way. 99% of the time this is the wrong solution.

This is how you do it:

FormatterServices.GetUninitializedObject(typeof(MyClass));

Call it in place of the object's constructor. It will create and return you an instance without calling any constructors or field initializers.

When you deserialize an object in WCF, it uses this method to create the object. When this happens, constructors and even field initializers are not run.

Neil
  • 7,227
  • 5
  • 42
  • 43
  • 3
    Welp, that solved my problem! Trying to avoid a parent object's constructor's DB calls when running unit tests on an inherited class. – Tarka Jul 26 '13 at 16:20
  • 2
    FormatterServices.GetUninitializedObject(typeof(MyClass)); will still call static constructors, however. – Paul Suart Jan 15 '14 at 20:40
  • @PaulSuart, good point. I have updated my answer to reflect that. – Neil Apr 30 '14 at 21:05
  • This is a code smell, even in unit tests. "Program to an interface, not to an implementation" so for instance if you are trying to fake a DbContext, you should probably using IObjectContextAdapter or extracting an interface from your custom context. – Jacob Brewer Feb 11 '18 at 17:44
  • Another reason to not like WCF ;) – Jacob Brewer Feb 11 '18 at 17:47
  • 1
    I used this to create a dummy WPF window in unit tests without it complaining about the thread needing to be STA. – Lee D Mar 05 '21 at 12:38
26

If you do not explicitly call any constructor in the base class, the parameterless constructor will be called implicitly. There's no way around it, you cannot instantiate a class without a constructor being called.

Tron
  • 1,397
  • 10
  • 11
  • 4
    Actually, if you read my comment below, there is a way, although I wouldn't recommend it in most cases. – Neil Oct 21 '08 at 17:44
  • 5
    This answer is simply wrong. Especially in the light of the other answer. – Kobor42 Mar 31 '15 at 08:50
6

At least 1 ctor has to be called. The only way around it I see is containment. Have the class inside or referencing the other class.

David Hall
  • 32,624
  • 10
  • 90
  • 127
mattlant
  • 15,384
  • 4
  • 34
  • 44
  • This is the path that is getting me the most results. Thanks! – casademora Oct 01 '08 at 19:55
  • May I add, using containment is the most typical way of implementing a proxy pattern. You usually instance the proxy explicitly, and make it implement the same interface as the proxied object: `MyInterface myProxy = new MyProxiedClass(new MyClass());` – jjmontes Oct 08 '20 at 16:40
5

I don't believe you can get around calling the constructor. But you could do something like this:

public class BaseClass : SomeOtherBase 
{
   public BaseClass() {}

   protected virtual void Setup()
   {
   }
}

public BaseClassProxy : BaseClass
{
   bool _fakeOut;
   protected BaseClassProxy(bool fakeOut)
   {
        _fakeOut = fakeOut;
        Setup();
   }

   public override void Setup()
   {
       if(_fakeOut)
       {
            base.Setup();
       }
       //Your other constructor code
   }
} 
Jake Pearson
  • 27,069
  • 12
  • 75
  • 95
5

If what you want is to not call either of the two base class constructors, this cannot be done.

C# class constructors must call base class constructors. If you don't call one explicitly, base( ) is implied. In your example, if you do not specify which base class constructor to call, it is the same as:

public BaseClassProxy : BaseClass
{
    public BaseClassProxy() : base() { }
}

If you prefer to use the other base class constructor, you can use:

public BaseClassProxy : BaseClass
{
    public BaseClassProxy() : base(someIntValue) { }
}

Either way, one of the two will be called, explicitly or implicitly.

Lucas
  • 17,277
  • 5
  • 45
  • 40
1

I am affraid that not base calling constructor isn't option.

Jakub Šturc
  • 35,201
  • 25
  • 90
  • 110
1

When you create a BaseClassProxy object it NEEDS to create a instance of it's base class, so you need to call the base class constructor, what you can doo is choose wich one to call, like:

public BaseClassProxy (bool fakeOut) : base (10) {}

To call the second constructor instead of the first one

albertein
  • 26,396
  • 5
  • 54
  • 57
0

I ended up doing something like this:

public class BaseClassProxy : BaseClass 
{
   public BaseClass BaseClass { get; private set; }

   public virtual int MethodINeedToOverride(){}
   public virtual string PropertyINeedToOverride() { get; protected set; }
}

This got me around some of the bad practices of the base class.

casademora
  • 67,775
  • 17
  • 69
  • 78
0

All right, here is an ugly solution to the problem of one class inheriting the constructors of another class that I didn't want to allow some of them to work. I was hoping to avoid using this in my class but here it is:

Here is my class constructor:

public MyClass();
{
   throw new Exception("Error: Must call constructor with parameters.");
}

OK now you were warned that it was ugly. No complaints please!

I wanted to force at least the minimal parameters from my main constructor without it allowing the inherited base constructor with no parameters.

I also believe that if you create a constructor and do not put the : base() after it that it will not call the base class constructor. And if you create constructors for all of the ones in the base class and provide the same exact parameters for them in the main class, that it will not pass through. But this can be tedious if you have a lot of constructors in the base class!

John Foll
  • 121
  • 1
  • 10
0

It is possible to create an object without calling the parameterless constructor (see answer above). But I use code like this to create a base class and an inherited class, in which I can choose whether to execute the base class's init.

public class MyClass_Base
{
    public MyClass_Base() 
    {
        /// Don't call the InitClass() when the object is inherited
        /// !!! CAUTION: The inherited constructor must call InitClass() itself when init is needed !!!
        if (this.GetType().IsSubclassOf(typeof(MyClass_Base)) == false)
        {
            this.InitClass();
        }
    }

    protected void InitClass()
    {
        // The init stuff
    }
}


public class MyClass : MyClass_Base
{
    public MyClass(bool callBaseClassInit)
    {
        if(callBaseClassInit == true)
            base.InitClass();
    }
}
marsh-wiggle
  • 2,508
  • 3
  • 35
  • 52
0

Here is my solution to the problem

using System;

public class Program
{
    public static void Main()
    {
        Console.WriteLine(new Child().Test);
    }

    public class Child : Parent {
        public Child() : base(false) {
            //No Parent Constructor called
        }
    }
    public class Parent {
        public int Test {get;set;}
        public Parent()
        {
            Test = 5;
        }
        public Parent(bool NoBase){
            //Don't do anything
        }
    }
}

A simple elegant solution. You can change it according to your need.

Noob Guy
  • 3
  • 2
0

Another simple solution from me:

class parent
{
    public parent()
    {
        //code for all children

        if (this.GetType() == typeof(child1))
        {
            //code only for objects of class "child1"
        }
        else
        {
            //code for objects of other child classes
        }
    }
}

class child1 : parent
{
    public child1()
    {}
}

// class child2: parent ... child3 : parent ... e.t.c
0

constructors are public by nature. do not use a constructor and use another for construction and make it private.so you would create an instance with no paramtersand call that function for constructing your object instance.

Uğur Gümüşhan
  • 2,455
  • 4
  • 34
  • 62