locked
Error: An object reference is required for the non-static field method and property ...

    Question

  • I've looked at the error message from MSDN and several posts about the error. Can't see where I fouled up. I've tried leaving out 'readonly', substituting 'const' and doing other strange and wond'rous things. It's clear I don't understand the issues and as a newbie in C# am inappropriately applying C/C++ and Java knowledge to C#.

    'MyMenuHandler is an abstract base class for VowelCounting and WordCounting. The goal is to provide a reference to a function like C/C++ contained in a concrete object. I can't do this in C# because delegates refer to static functions, leaving out access to object functions and fields. The alternative (I thought) would be to provide a reference to an instantiated class and refer to the function by name - this defeats the design goal of making the system unaware of the function being called other than the input arguments but, well, if it works it works. The use of arrays is to provide compile time instantiation of known objects/values, and then to automate functionality using known objects. Well, I can't get that going either. Any help would be nice, and if the help allows me to understand previous postings on this topic, so much the better.

    I didn't use interfaces because there is just so much to learn in a day and I'm already befuddled.

    thanks

    art

          public struct Menu {
             public readonly string        menuItem;    //!< string for menu iten
             public readonly MyMenuHandler menuHandler; //!< concrete object to handle menu item
             public readonly bool          printFlag;   //!< controls menu output printing
    
             public Menu(string menuItem, MyMenuHandler menuHandler, bool printFlag = true) {
                this.menuItem    = menuItem;
                this.menuHandler = menuHandler;
                this.printFlag   = printFlag;
             } // void Menu(string menuItem, MenuHandler menuHandler, bool property)
          }; // struct menu
       
       class Test 
       {
          readonly MyMenuHandler[] obj = { new VowelCounting()
                                         , new WordCounting()
                                         }; // MyMenuHandler[] obj 
    
          private const Menu[] menu = { new Menu("Word counting.", obj[1], true)
                                      , new Menu("Word counting.", obj[0], true)
                                      }; // const Menu[] menu
    }
    


    Friday, January 27, 2012 10:13 PM

Answers

  • Scratch that. I did (the obvious) 'new MyMenuHandler[]' and it worked. So if you have time, how come the menu = new[] and not the obj = new?

     

    art

    Because you're using an abstract class in the first - so it doesn't see that type as the proper candidate, I think...  It's just a limitation of the type inferrence.

     


    Reed Copsey, Jr. - http://reedcopsey.com
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
    • Marked as answer by aschwarz Friday, January 27, 2012 11:22 PM
    Friday, January 27, 2012 11:06 PM
    Moderator

All replies

  • " . I can't do this in C# because delegates refer to static functions, leaving out access to object functions and fields."

     

    This isn't true.  A delegate can also refer to an instance function, without issue.

     

    That being said, the problem here is that you're trying to instantiate your "menu" array in an inline initializer as a const (both of which won't work), but referring to class members that are non-static (obj).  You could correct this by using a constructor to initialize both of your arrays, like so:

       class Test 
       {
          MyMenuHandler[] obj;
          private Menu[] menu;
    
          public Test()
          {
             obj = new[]{ new VowelCounting()
                                         , new WordCounting()
                                         }; // MyMenuHandler[] obj 
    
             menu = new[]{ new Menu("Word counting.", obj[1], true)
                                      , new Menu("Word counting.", obj[0], true)
                                      }; // Menu[] menu
          }
    }
    
    

    Note that you can't use const, as const (in C#) is only usable for things that are compile time constants.  This means you can't refer to other types (obj) within their initialization.  


    Reed Copsey, Jr. - http://reedcopsey.com
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
    Friday, January 27, 2012 10:26 PM
    Moderator
  • I'm not sure I follow exactly what you're trying to do. It's certainly possible to map a delegate to a C# instance method if you want - it doesn't have to be a static method. You just have to define a delegate type for it. For example, if you want a menu item which can trigger any method which takes no parameters, you could write it something like this:

    public class Menu
    {
            private readonly string _label;
            private readonly Action _methodToCall;
            private readonly bool _printFlag;
    
            public Menu(string label, Action methodToCall, bool printFlag = true)
            {
                    this._label = label;
                    this._methodToCall = methodToCall;<pre>Test newTest = new Test();
    Menu newMenu = new Menu("testLabel", newTest.TestMethod, true);
    
    newMenu.FireMethod();
    

    this._printFlag = printFlag; } public void FireMethod() { _methodToCall(); } } class Test { public void TestMethod() { MessageBox.Show("TestMethod called"); } }

    Then, in your program's Main method, add this:

     

    Test newTest = new Test();
    Menu newMenu = new Menu("test", newTest.TestMethod, true);
    	
    newMenu.FireMethod();

    All that aside, back to your actual question - you need to set the values of menu and obj in your Test class in the Test() constructor rather than trying to do it in-line like that.

     

    EDIT: Or, in other words, exactly what Reed said above. He answered while I was writing my answer.


    Check out My Blog. Now updated to actually work!
    Friday, January 27, 2012 10:46 PM
  • You have been very, very helpful in explaining what I did incorrectly. Now (sigh) there is still an error, but it's only fatal and so nothing to worry about. I would be quite content with a 'worst type', I don't need the 'best'.

    art

         MyMenuHandler[] obj; // MyMenuHandler[] obj 
    
          Menu[] menu; 
    
          public Test() {
             obj = new[]    // no best type found for implicitly defined array
                 { new WordCounting()
                 , new VowelCounting()
                 }; // MyMenuHandler[] obj 
    
             menu = new[]
                  { new Menu("Word counting.",  obj[0], true)
                  , new Menu("Vowel counting.", obj[1], true)
                  }; // const Menu[] menu
                  
          } // Test()
    


    Friday, January 27, 2012 11:01 PM
  • Scratch that. I did (the obvious) 'new MyMenuHandler[]' and it worked. So if you have time, how come the menu = new[] and not the obj = new?

     

    art

    Friday, January 27, 2012 11:03 PM
  • Scratch that. I did (the obvious) 'new MyMenuHandler[]' and it worked. So if you have time, how come the menu = new[] and not the obj = new?

     

    art

    Because you're using an abstract class in the first - so it doesn't see that type as the proper candidate, I think...  It's just a limitation of the type inferrence.

     


    Reed Copsey, Jr. - http://reedcopsey.com
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
    • Marked as answer by aschwarz Friday, January 27, 2012 11:22 PM
    Friday, January 27, 2012 11:06 PM
    Moderator