Results 1 to 6 of 6

Thread: [RESOLVED] 'Virtual member call in constructor'

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Resolved [RESOLVED] 'Virtual member call in constructor'

    Hi,

    I got an abstract class BasePage that inherits System.Web.UI.Page for a web application, and actual pages are supposed to inherit this BasePage instead of Page directly.

    The BasePage needs to create some object in its constructor using a Configuration. A Configuration is a class related to NHibernation (doesn't really matter for my question).
    However, as far as I know I cannot pass this configuration via the constructor because in ASP.NET you never call the constructor of a page directly (in each case, I wouldn't know how to pass parameters to the constructor of a page even if it is possible).

    So I need some other way to get the information in the constructor. I thought I could use an abstract property that the derived class has to override in which it can return the Configuration object, so I did this:
    csharp Code:
    1. public abstract class BasePage : System.Web.UI.Page
    2. {
    3.     public BasePage()  // cannot use parameters here
    4.     {
    5.         // Get the configuration it needs to use
    6.         Configuration config = this.Configuration;
    7.  
    8.         // And use it
    9.         this.CreateObjectFromConfiguration(config);
    10.     }
    11.  
    12.     public abstract Configuration Configuration { get; }
    13.  
    14.     //...
    15. }
    My reasoning is that now, a deriving page can do supply the configuration from wherever it gets it from (for example, a session variable or whatever):
    csharp Code:
    1. public class ActualPage : BasePage
    2. {
    3.     public override Configuration Configuration
    4.     {
    5.         get { return (Configuration)this.Session["Configuration"]; }
    6.     }
    7. }


    While conceptually this seemed to fit, ReSharper gave me a warning on line 6 of the first code sample, saying "Virtual member call in constructor". I googled the warning and I came up with a few threads that explain why this can be a problem. If I understand it correctly, in my example, the constructor of BasePage would request the Configuration property in the deriving class (ActualPage.Configuration), but the deriving class has not been created yet. I guess that this.Session["Configuration"] would then return null?

    I am not in the opportunity to test it with the actual page objects at the moment, so I created a little test where I replaced Configuration with a simple Button:
    csharp Code:
    1. class Program
    2.     {
    3.         static void Main(string[] args)
    4.         {
    5.             var page = new ActualPage();
    6.         }
    7.     }
    8.    
    9.     public abstract class BasePage
    10.     {
    11.         public BasePage()  
    12.         {
    13.             Button btn = this.Button;
    14.  
    15.             Debug.WriteLine(btn.Text);
    16.         }
    17.  
    18.         public abstract Button Button { get; }
    19.     }
    20.  
    21.     public class ActualPage : BasePage
    22.     {
    23.         private Button b;
    24.  
    25.         public ActualPage()
    26.         {
    27.             b = new Button {Text = "test"};
    28.         }
    29.  
    30.         public override Button Button
    31.         {
    32.             get { return b; }
    33.         }
    34.     }
    Indeed, when I run this, I get a null reference exception on the Debug.WriteLine method as 'btn' is null.



    How can I solve this problem? How can I pass the Configuration (or the Button in my example) to the constructor of the BasePage without passing it via a parameter as usual?

    Thanks!

  2. #2
    C# Aficionado Lord_Rat's Avatar
    Join Date
    Sep 2001
    Location
    Cave
    Posts
    2,497

    Re: 'Virtual member call in constructor'

    Isn't the base constructor called before the derived constructor? If so, then the problem is simply order of operations. I'm going to do a double check online, but I believe with abstract classes, that's the case.

    Edit: I am embarking on this search but perhaps before I do, I should point out the way I usually go about these things.

    I create a constructor in the base class, but not the derived class. It called a virtual method that actually does my constructing. The derived class overrides the virtual method and give it innards.

    Code:
    class BaseClass
    {
        public BaseClass(string param, int param2){
            DoInit(string param, int param2);
        }
    
        private abstract void DoInit(string param, int param2);
    }
    
    class DerivedClass : BaseClass
    {
       private override void DoInit(string param, int param2){
          //Do Work
       }
    }
    Edit 2: I am indeed correct on the order of operations. Constructors are executed according to the order of inheritance.
    Last edited by Lord_Rat; Jan 12th, 2011 at 01:48 PM.
    Need to re-register ASP.NET?
    C:\WINNT\Microsoft.NET\Framework\v#VERSIONNUMBER#\aspnet_regiis -i

    (Edit #VERSIONNUMBER# as needed - do a DIR if you don't know)

  3. #3

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: 'Virtual member call in constructor'

    Yes, that is what I found as well, but that is exactly the problem. The BasePage constructor is getting a property on the derived class, which is not created yet (or not 'constructed' yet, I dunno if there's a difference).

    In the meantime I found a way to delay the getting and using of Configuration (until it's actually required) but I'd rather do it in the constructor.

  4. #4
    C# Aficionado Lord_Rat's Avatar
    Join Date
    Sep 2001
    Location
    Cave
    Posts
    2,497

    Re: 'Virtual member call in constructor'

    The edit I added should handle that though. Just move the construction of the button to the equivelant of the "DoInit".
    Need to re-register ASP.NET?
    C:\WINNT\Microsoft.NET\Framework\v#VERSIONNUMBER#\aspnet_regiis -i

    (Edit #VERSIONNUMBER# as needed - do a DIR if you don't know)

  5. #5

  6. #6
    C# Aficionado Lord_Rat's Avatar
    Join Date
    Sep 2001
    Location
    Cave
    Posts
    2,497

    Re: [RESOLVED] 'Virtual member call in constructor'

    No problem! Sometimes, it just takes turning the problem on its side to see the solution. =)
    Need to re-register ASP.NET?
    C:\WINNT\Microsoft.NET\Framework\v#VERSIONNUMBER#\aspnet_regiis -i

    (Edit #VERSIONNUMBER# as needed - do a DIR if you don't know)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width