Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. Managed C++/CLI
  4. Trivial Property not working

Trivial Property not working

Scheduled Pinned Locked Moved Managed C++/CLI
data-structuresdebugging
9 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • I Offline
    I Offline
    iddqd515
    wrote on last edited by
    #1

    I'm getting really confused by trivial properties. Can someone explain this to me:

    #include "stdafx.h"

    using namespace System;

    ref class Foo
    {
    public:
    // default constructor, initializes data members to non null values
    Foo()
    {
    data = 0;
    s = "default";
    }
    // constructor with 2 parameters, initializes data members to non null values
    Foo(int d, String^ in)
    {
    data = d;
    s = in;
    }
    virtual String^ ToString() override
    {
    return "Data: " + this->Data + " S: " + this->S;
    }

    // I'm writing the properties explicitly
    // In theory, there is no reason I shouldn't be able to use trivial property
    // declarations in place of these two
    property int Data
    {
    int get()
    {
    return data;
    }
    void set(int d )
    {
    data = d;
    }

    }
    property String^ S
    {
    String^ get()
    {
    return s;
    }
    void set(String^ in)
    {
    s = in;
    }
    }
    // The trivial property declarations which are giving me trouble when I try to use them
    // property int Data;
    // property String^ S;

    // This is commented out just for demonstration purposes
    // With the current code these could be made private and things would still work
    // private:
    int data;
    String^ s;
    };

    int main(array ^args)
    {
    // create Foo objects in a bunch of ways
    // none of them should have any null members
    Foo f;
    Foo b(1, "hello");
    Foo ^c = gcnew Foo(5, "world");

    // this will obviously fail if you make the data members private
    // In the current form, this prints out the correct values
    Console::WriteLine(f.data + " " + f.s->ToString());
    Console::WriteLine(b.data + " " + b.s->ToString());
    Console::WriteLine(c->data + " " + c->s->ToString());
    
    // This block prints correctly when using the explicit property declarations currently in use
    // whether the data members are private or public.
    // If I use the trivial property declarations (currently commented out) instead
    // then this block causes NullReferenceExceptions when trying to access S.
    // If I debug I notice that the  for each member made by the trivial property
    // is not being set but there is a properly set Data and S field.
    Console::WriteLine(f.Data + " " + f.S->ToString());
    Console::WriteLine(b.Data + " " + b.S->ToString());
    Console::WriteLine(c->Data + " "
    
    M I 2 Replies Last reply
    0
    • I iddqd515

      I'm getting really confused by trivial properties. Can someone explain this to me:

      #include "stdafx.h"

      using namespace System;

      ref class Foo
      {
      public:
      // default constructor, initializes data members to non null values
      Foo()
      {
      data = 0;
      s = "default";
      }
      // constructor with 2 parameters, initializes data members to non null values
      Foo(int d, String^ in)
      {
      data = d;
      s = in;
      }
      virtual String^ ToString() override
      {
      return "Data: " + this->Data + " S: " + this->S;
      }

      // I'm writing the properties explicitly
      // In theory, there is no reason I shouldn't be able to use trivial property
      // declarations in place of these two
      property int Data
      {
      int get()
      {
      return data;
      }
      void set(int d )
      {
      data = d;
      }

      }
      property String^ S
      {
      String^ get()
      {
      return s;
      }
      void set(String^ in)
      {
      s = in;
      }
      }
      // The trivial property declarations which are giving me trouble when I try to use them
      // property int Data;
      // property String^ S;

      // This is commented out just for demonstration purposes
      // With the current code these could be made private and things would still work
      // private:
      int data;
      String^ s;
      };

      int main(array ^args)
      {
      // create Foo objects in a bunch of ways
      // none of them should have any null members
      Foo f;
      Foo b(1, "hello");
      Foo ^c = gcnew Foo(5, "world");

      // this will obviously fail if you make the data members private
      // In the current form, this prints out the correct values
      Console::WriteLine(f.data + " " + f.s->ToString());
      Console::WriteLine(b.data + " " + b.s->ToString());
      Console::WriteLine(c->data + " " + c->s->ToString());
      
      // This block prints correctly when using the explicit property declarations currently in use
      // whether the data members are private or public.
      // If I use the trivial property declarations (currently commented out) instead
      // then this block causes NullReferenceExceptions when trying to access S.
      // If I debug I notice that the  for each member made by the trivial property
      // is not being set but there is a properly set Data and S field.
      Console::WriteLine(f.Data + " " + f.S->ToString());
      Console::WriteLine(b.Data + " " + b.S->ToString());
      Console::WriteLine(c->Data + " "
      
      M Offline
      M Offline
      Mark Salsbery
      wrote on last edited by
      #2

      Maybe I'm missing something, but how can you expect to read a property if you omit the getter function? Also, is using ToString on a String redundant? :) Mark

      Mark Salsbery Microsoft MVP - Visual C++ "Go that way, really fast. If something gets in your way, turn."

      I 1 Reply Last reply
      0
      • M Mark Salsbery

        Maybe I'm missing something, but how can you expect to read a property if you omit the getter function? Also, is using ToString on a String redundant? :) Mark

        Mark Salsbery Microsoft MVP - Visual C++ "Go that way, really fast. If something gets in your way, turn."

        I Offline
        I Offline
        iddqd515
        wrote on last edited by
        #3

        Unless I'm horribly mistaken... Declaring the trivial property as follows:

        property int Data;

        should tell the compiler to generate something to the effect of:

        property int Data
        {
        int get()
        {
        return data;
        }
        void set(int d)
        {
        data = d;
        }
        }

        using a ' < backing_store > Data' variable behind the scenes. Likewise for

        property String^ S

        That's the whole point of trivial properties as I understood it. If you're just making a 'trivial' getter and setter with no validation then the trivial property declaration should accomplish what you need and save you from typing a few lines of code. At least that's what I gathered from http://www.codeproject.com/managedcpp/CppCliProperties.asp?df=100&forumid=179807&exp=0&select=1107337 and many other articles/books. And yes, that was a little redundant :~ I've been staring at this property stuff for so long I'm making some dumb mistakes and triple checking everything before I post it. -- modified at 18:18 Tuesday 3rd July, 2007

        M 1 Reply Last reply
        0
        • I iddqd515

          I'm getting really confused by trivial properties. Can someone explain this to me:

          #include "stdafx.h"

          using namespace System;

          ref class Foo
          {
          public:
          // default constructor, initializes data members to non null values
          Foo()
          {
          data = 0;
          s = "default";
          }
          // constructor with 2 parameters, initializes data members to non null values
          Foo(int d, String^ in)
          {
          data = d;
          s = in;
          }
          virtual String^ ToString() override
          {
          return "Data: " + this->Data + " S: " + this->S;
          }

          // I'm writing the properties explicitly
          // In theory, there is no reason I shouldn't be able to use trivial property
          // declarations in place of these two
          property int Data
          {
          int get()
          {
          return data;
          }
          void set(int d )
          {
          data = d;
          }

          }
          property String^ S
          {
          String^ get()
          {
          return s;
          }
          void set(String^ in)
          {
          s = in;
          }
          }
          // The trivial property declarations which are giving me trouble when I try to use them
          // property int Data;
          // property String^ S;

          // This is commented out just for demonstration purposes
          // With the current code these could be made private and things would still work
          // private:
          int data;
          String^ s;
          };

          int main(array ^args)
          {
          // create Foo objects in a bunch of ways
          // none of them should have any null members
          Foo f;
          Foo b(1, "hello");
          Foo ^c = gcnew Foo(5, "world");

          // this will obviously fail if you make the data members private
          // In the current form, this prints out the correct values
          Console::WriteLine(f.data + " " + f.s->ToString());
          Console::WriteLine(b.data + " " + b.s->ToString());
          Console::WriteLine(c->data + " " + c->s->ToString());
          
          // This block prints correctly when using the explicit property declarations currently in use
          // whether the data members are private or public.
          // If I use the trivial property declarations (currently commented out) instead
          // then this block causes NullReferenceExceptions when trying to access S.
          // If I debug I notice that the  for each member made by the trivial property
          // is not being set but there is a properly set Data and S field.
          Console::WriteLine(f.Data + " " + f.S->ToString());
          Console::WriteLine(b.Data + " " + b.S->ToString());
          Console::WriteLine(c->Data + " "
          
          I Offline
          I Offline
          iddqd515
          wrote on last edited by
          #4

          Here's my other test case that is confusing the hell out of me. The errors/results/questions are all in the comments:

          #include "stdafx.h"

          using namespace System;

          // managed class with explicity copy constructor and assignment operator
          ref class Foo
          {
          public:
          Foo() {} // default constructor

          // constructor takes a single parameter
          // intialize value data member via direct access or through property
          Foo(int d)
          {
          Value = d; // (3)
          //value = d; // (4)
          }
          // copy constructor
          // could declare parameter const but then you can't use Value property
          Foo(Foo^ b) //: value(b->value) Initializer presumably doesn't work for the same reasons
          {
          //Value = b->Value; // (1)
          value = b->value; // (2)
          //value = b->Value; // Presumably doesn't work for the same reasons
          }

          // trivial property declaration, in theory creates the same code as the explicit below
          property int Value;

          // explicit property declaration
          /*property int Value
          {
          int get()
          {
          return value;
          }
          void set(int v)
          {
          value = v;
          }
          }*/

          // note: value must be public for Block B to work.
          // Public or private doesn't affect the following results.

          //private:
          int value;
          };

          int main (array ^)
          {
          // **************************************************************************
          // The following results are based on using the default constructor
          // and setting the value member after construction
          // Define 'works' to mean the copy constructor properly initializes the
          // value data member of the new Foo object to be equal to the value in the passed argument
          /* If the copy constructor uses (1) instead of (2):
          * TRIVIAL PROPERTY DECLARED: Block A works, Block B doesn't work
          * EXPLICIT PROPERTY DECLARED: Block A works, Block B works

           \* If the copy constructor uses (2) instead of (1):
           \* TRIVIAL PROPERTY DECLARED: Block A doesn't work, Block B works
           \* EXPLICIT PROPERTY DECLARED: Block A works, Block B works
           \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
          

          // *****************************************************************************
          // The following results are based on using the single parameter constructor
          // to set the value data member
          /* If the single parameter constructor uses (4) instead of (3):
          * TRIVIAL PROPERTY DECLARED: Block A doesn't work, Block B wor

          D 1 Reply Last reply
          0
          • I iddqd515

            Unless I'm horribly mistaken... Declaring the trivial property as follows:

            property int Data;

            should tell the compiler to generate something to the effect of:

            property int Data
            {
            int get()
            {
            return data;
            }
            void set(int d)
            {
            data = d;
            }
            }

            using a ' < backing_store > Data' variable behind the scenes. Likewise for

            property String^ S

            That's the whole point of trivial properties as I understood it. If you're just making a 'trivial' getter and setter with no validation then the trivial property declaration should accomplish what you need and save you from typing a few lines of code. At least that's what I gathered from http://www.codeproject.com/managedcpp/CppCliProperties.asp?df=100&forumid=179807&exp=0&select=1107337 and many other articles/books. And yes, that was a little redundant :~ I've been staring at this property stuff for so long I'm making some dumb mistakes and triple checking everything before I post it. -- modified at 18:18 Tuesday 3rd July, 2007

            M Offline
            M Offline
            Mark Salsbery
            wrote on last edited by
            #5

            :) It's me that's horribly mistaken. When you initialize the trivial proprties in your constructors, you need to use the trivial property names:

            // default constructor, initializes data members to non null values
            Foo()
            {
            Data = 0;
            S = "default";
            }

            // constructor with 2 parameters, initializes data members to non null values
            Foo(int d, String^ in)
            {
            Data = d;
            S = in;
            }
            ...
            property int Data;
            property String^ S;

            Mark

            Mark Salsbery Microsoft MVP - Visual C++ "Go that way, really fast. If something gets in your way, turn."

            I 1 Reply Last reply
            0
            • M Mark Salsbery

              :) It's me that's horribly mistaken. When you initialize the trivial proprties in your constructors, you need to use the trivial property names:

              // default constructor, initializes data members to non null values
              Foo()
              {
              Data = 0;
              S = "default";
              }

              // constructor with 2 parameters, initializes data members to non null values
              Foo(int d, String^ in)
              {
              Data = d;
              S = in;
              }
              ...
              property int Data;
              property String^ S;

              Mark

              Mark Salsbery Microsoft MVP - Visual C++ "Go that way, really fast. If something gets in your way, turn."

              I Offline
              I Offline
              iddqd515
              wrote on last edited by
              #6

              Right, I just didn't see why simply declaring the trivial property (instead of an explicit getter and setter) caused accessing the member variables directly not to work. Nor had I ever seen mention of this fact. If declaring a property makes it so you can't access the member properly without it that seems like something that should've been mentioned somewhere...

              M 1 Reply Last reply
              0
              • I iddqd515

                Right, I just didn't see why simply declaring the trivial property (instead of an explicit getter and setter) caused accessing the member variables directly not to work. Nor had I ever seen mention of this fact. If declaring a property makes it so you can't access the member properly without it that seems like something that should've been mentioned somewhere...

                M Offline
                M Offline
                Mark Salsbery
                wrote on last edited by
                #7

                You can access them. Using your code only failed for me when using the trivial properties because the constructors were setting the non-trivial property variable names (actually they weren't even properties at that point - they're just member variables). That left the trivial property "S" uninitialized, causing a NULL exception when accessed. Once you get rid of these variables // private: int data; String^ s; and access these instead property int Data; property String^ S; it works fine. For me it was a good example of why having two variable names that differ only in case is a recipe for disaster :) Mark

                Mark Salsbery Microsoft MVP - Visual C++ "Go that way, really fast. If something gets in your way, turn."

                1 Reply Last reply
                0
                • I iddqd515

                  Here's my other test case that is confusing the hell out of me. The errors/results/questions are all in the comments:

                  #include "stdafx.h"

                  using namespace System;

                  // managed class with explicity copy constructor and assignment operator
                  ref class Foo
                  {
                  public:
                  Foo() {} // default constructor

                  // constructor takes a single parameter
                  // intialize value data member via direct access or through property
                  Foo(int d)
                  {
                  Value = d; // (3)
                  //value = d; // (4)
                  }
                  // copy constructor
                  // could declare parameter const but then you can't use Value property
                  Foo(Foo^ b) //: value(b->value) Initializer presumably doesn't work for the same reasons
                  {
                  //Value = b->Value; // (1)
                  value = b->value; // (2)
                  //value = b->Value; // Presumably doesn't work for the same reasons
                  }

                  // trivial property declaration, in theory creates the same code as the explicit below
                  property int Value;

                  // explicit property declaration
                  /*property int Value
                  {
                  int get()
                  {
                  return value;
                  }
                  void set(int v)
                  {
                  value = v;
                  }
                  }*/

                  // note: value must be public for Block B to work.
                  // Public or private doesn't affect the following results.

                  //private:
                  int value;
                  };

                  int main (array ^)
                  {
                  // **************************************************************************
                  // The following results are based on using the default constructor
                  // and setting the value member after construction
                  // Define 'works' to mean the copy constructor properly initializes the
                  // value data member of the new Foo object to be equal to the value in the passed argument
                  /* If the copy constructor uses (1) instead of (2):
                  * TRIVIAL PROPERTY DECLARED: Block A works, Block B doesn't work
                  * EXPLICIT PROPERTY DECLARED: Block A works, Block B works

                   \* If the copy constructor uses (2) instead of (1):
                   \* TRIVIAL PROPERTY DECLARED: Block A doesn't work, Block B works
                   \* EXPLICIT PROPERTY DECLARED: Block A works, Block B works
                   \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
                  

                  // *****************************************************************************
                  // The following results are based on using the single parameter constructor
                  // to set the value data member
                  /* If the single parameter constructor uses (4) instead of (3):
                  * TRIVIAL PROPERTY DECLARED: Block A doesn't work, Block B wor

                  D Offline
                  D Offline
                  Daniel Grunwald
                  wrote on last edited by
                  #8

                  "property int Value;" creates it's own member variable to store the value, it won't use "int value;". So you got two members (one property "Value" and one field "value") that are unrelated and store different values.

                  I 1 Reply Last reply
                  0
                  • D Daniel Grunwald

                    "property int Value;" creates it's own member variable to store the value, it won't use "int value;". So you got two members (one property "Value" and one field "value") that are unrelated and store different values.

                    I Offline
                    I Offline
                    iddqd515
                    wrote on last edited by
                    #9

                    So it seems. I'm just confused because all the postings I've seen about it have said you can write a trivial property declaration just like I did in place of the type of explicit one that I did (i.e., no mention of making sure to name the trivial property differently). It makes it incredibly confusing if your trivial property has the exact same name (case and all) as a data member... so confusing as to be useless in my opinion...

                    1 Reply Last reply
                    0
                    Reply
                    • Reply as topic
                    Log in to reply
                    • Oldest to Newest
                    • Newest to Oldest
                    • Most Votes


                    • Login

                    • Don't have an account? Register

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • World
                    • Users
                    • Groups