locked
C# property with parameters?

    Question

  • Is there anyway to pass a parameter to a property in C# like you would in vb.net

    I have some old VB code that wraps an XPath search to "touch" the path and then set or return the value. So you can have an xml object with just "<ROOT_NODE />" and call:

    xmlObject.E("ROOT_NODE/CHILD/VALUE") = "1"

    The above would create the "CHILD" node and the "VALUE" node and give the "VALUE" node a text of "1".  The XPath is passed as a parameter of the property.  So now I need to see if I can make a backwards compatible version in C#.  I have the "touch" logic working I just do not know how to make the syntax work the same.

    Does anyone know how to do this in C#?
    Thursday, September 07, 2006 10:36 PM

Answers

  • Here is an example

    Examplepublic WebSite this[int index]
    {
       get
          {   
              if (index > sites.Count)   
                return (WebSite)null;   

              return (WebSite) sites.GetByIndex(index);
          }
       set
          {   
             if ( index < 10 )   
               sites[index] = value;
          }
    }
    Saturday, September 09, 2006 9:25 PM
    Moderator

All replies

  • The only type of parameterized property you can define in C# is indexers (aka default properties).

     

    Friday, September 08, 2006 8:25 AM
  • Here is an example

    Examplepublic WebSite this[int index]
    {
       get
          {   
              if (index > sites.Count)   
                return (WebSite)null;   

              return (WebSite) sites.GetByIndex(index);
          }
       set
          {   
             if ( index < 10 )   
               sites[index] = value;
          }
    }
    Saturday, September 09, 2006 9:25 PM
    Moderator
  • Here is another example:

     

    Code Block

    class MyClass
    {
        string[] _myArray = new string[5];

        public string this[int index]
        {
            get
            {
                return _myArray[index];
            }
            set
            {
                _myArray[index] = value;
            }
        }
    }

     

     

    Code Block

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            MyClass myClass = new MyClass();
            myClass[0] = "New Text";
            MessageBox.Show(myClass[0]);
        }
    }

     

     

    Tuesday, November 13, 2007 8:32 AM
  • > The only type of parameterized property you can define in C# is indexers (aka default properties).

    Yes, that's true - but why?


    Perhaps an explanation could be added to the "ask a language designer" page.
    Tuesday, December 04, 2007 10:05 AM
  • Nevertheless, a class can have a field (or a property) that itself has an indexer. This then looks like a property with parameters.

     

    Continuing Sinan's example:

     

    Code Block

    class X
    {
       public MyClass Strings = new MyClass();
    }

     

     

    You can then write:

     

    Code Block

    X x = new X();

    x.Strings[2] = "...";

     

     

    Tuesday, December 04, 2007 10:40 AM
  • Thanks Martin - that does cover most use cases, at least from the point of view of the consumer of the property.

    Unfortunately it does mean you have to create a whole extra type if you just want to add some custom logic to the parameterized getter/setters.
    Tuesday, December 04, 2007 11:20 AM
  • But there is also a property in CaptureCollection that has parameter like indexer :

    public
     Capture
     Item
    [
    int i
    ] { get ; }
    Any explanation?
    Wednesday, October 21, 2009 3:18 PM
  • Item is just the default name for an indexer property.

    It is hidden in C#. A vb program can use cc(i) or cc.Item(i) to call it.
    Wednesday, October 21, 2009 4:24 PM
  • You might try a more generic, reusable technique. You could define a general-purpose "parameterized property" class like this: 

      // Generic, parameterized (indexed) "property" template
      public class Property<T>
      {
       // The internal property value
       private T PropVal = default(T);
    
       // The indexed property get/set accessor 
       // (Property<T>[index] = newvalue; value = Property<T>[index];)
       public T this[object key]
       {
        get { return PropVal; }  // Get the value
        set { PropVal = value; } // Set the value
       }
      }
    
    

    Then, you could implement one or more parameterized properties in your public class like this:
      public class ParameterizedProperties
      {
       // Parameterized properties
       private Property<int> m_IntProp = new Property<int>();
       private Property<string> m_StringProp = new Property<string>();
    
       // Parameterized int property accessor for client access
       // (ex: ParameterizedProperties.PublicIntProp[index])
       public Property<int> PublicIntProp
       {
        get { return m_IntProp; }
       }
    
       // Parameterized string property accessor
       // (ex: ParameterizedProperties.PublicStringProp[index])
       public Property<string> PublicStringProp
       {
        get { return m_StringProp; }
       }
      }
    
    

    Finally, the client could access your public class like this:
       ParameterizedProperties parmProperties = new ParameterizedProperties();
       parmProperties.PublicIntProp[1] = 100;
       parmProperties.PublicStringProp[1] = "whatever";
       int ival = parmProperties.PublicIntProp[1];
       string strVal = parmProperties.PublicStringProp[1];
    
    

    The "indexer" or "parameter" for your public properties (in this case, an object called "key") could be anything -- an index, a key string, a security-accessor object, etc. Also, to provide custom processing based on the client's supplied property parameter (index), you could just override the generic Property<T> and expose your override subclass as the public property type.

    Good luck!

    Mark Jones


    Mark Jones
    Saturday, June 11, 2011 1:58 AM