CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 10 of 10
  1. #1
    Join Date
    Nov 2006
    Posts
    357

    Question about method with ref argument

    Hey,

    Hopefully a simple question, heres some code:

    Code:
    class A { public int Var1; }
    class B : A { public int Var2; }
    
    class C
    {
       public static A GetA() 
       {
          A Var = new A();
          generateA(Var);
          return Var;
       }
    
       public static A GetB()
       {
          A Var = new B();
          generateA(ref Var);
          generateB(ref Var); // Error
          return Var;
       }
    
       protected static generateA(ref A Var)
       { Var.Var1 = 1; }
    
       protected static generateB(ref B Var)
       { Var.Var2 = 2; }
    
    }
    Now thats just a simple example of what im trying to do, but it seems to kick up a fuss when i try to pass over a base type that is acctually a subclass. In my real code i have a few methods that build up classes internal members, so one method for each sub class, that way i can reuse the code to build up the subclasses by populating in order...

    Anyway hopefully that shows what im trying to do, any help or advice would be great!
    Last edited by Grofit; May 17th, 2009 at 07:02 AM.

  2. #2
    Join Date
    Jun 2008
    Posts
    2,477

    Re: Question about method with ref argument

    Well, there are a couple of problems. A is not a B, so you can't pass it in its place. You can pass in a B for an A, but the other way around does not make sense. It has nothing to do with the ref specifier. Even though the A is a B under the hood, you cannot implicitly convert and A to a B, so you must cast it.

    Also, you have to pass them in using the 'ref' keyword or it will not compile.

  3. #3
    Join Date
    Nov 2006
    Posts
    357

    Re: Question about method with ref argument

    Oh sorry that was a typo on my behalf, will update the previous post.

    The whole point of polymorphism is that you have a shared base type but cast it at runtime to be an inherited type. So there shouldnt be problem casting from A -> B, providing it is an instance of B within the A object.

    If i remove the refs and do a manual cast it works fine, but then any updates i would do to the object wouldnt persist. I would make it of type B to begin with if i could, but then the first method would kick up a fuss saying that B isnt an A object, which is stupid as of course B is of type A as it inherits from it...

    So im thinking that ref handles objects differently, maybe i could cast it from A to whatever object it needs when im within the method...

  4. #4
    Join Date
    May 2007
    Posts
    1,546

    Re: Question about method with ref argument

    Code:
    class A { public int Var1; }
    class B : A { public int Var2; }
    
    class C
    {
    
       public static A GetB()
       {
          A Var = new B();
          generateB(ref Var); // Error
          return Var;
       }
       protected static generateB(ref B Var)
       { Var.Var2 = 2; }
    }
    What that method call is trying to say is that an 'A' *is a* 'B'. However this is not true, the opposite is true. You can't pass an 'A' in the place of a 'B' argument. It's like trying to feed a steak to a vegetarian. It just doesn't won't work

    Sure, in this exact case it can be statically determined that Var is actually a 'B', but as you've declared it of type 'A' and tried to pass it to an argument of incompatible type 'B', you fail. The C# compiler doesn't allow you to do (broken) stuff like this. It's a good compiler
    www.monotorrent.com For all your .NET bittorrent needs

    NOTE: My code snippets are just snippets. They demonstrate an idea which can be adapted by you to solve your problem. They are not 100% complete and fully functional solutions equipped with error handling.

  5. #5
    Join Date
    Nov 2006
    Posts
    357

    Re: Question about method with ref argument

    Its technically not broken though, i can see why it does it, but if i were to do the following:

    Code:
    class A { public int Var1; }
    class B : A { public int Var2; }
    
    class C
    {
       public static A GetA() 
       {
          A Var = new A();
          generateA(Var);
          return Var;
       }
    
       public static A GetB()
       {
          B Var = new B();
          generateA(ref Var); // Error
          generateB(ref Var);
          return Var;
       }
    
       protected static generateA(ref A Var)
       { Var.Var1 = 1; }
    
       protected static generateB(ref B Var)
       { Var.Var2 = 2; }
    
    }
    I get the same error just the other way round on the generateA() function. It would be fine if it allowed me to pass in a B as an A, but neither way works so im a bit stumped as to how i can build up different parts of a class this way, or im going to have to duplicate the generateA() code into the generateB/C/D/E methods etc...

    I can understand that B object *is not an* A object, however it is 100% guarenteed that B *does have* the same members as an A object, so why does it kick up a fuss in this regard?
    Last edited by Grofit; May 17th, 2009 at 03:00 PM.

  6. #6
    Join Date
    Jun 2008
    Posts
    2,477

    Re: Question about method with ref argument

    Quote Originally Posted by Grofit View Post
    Oh sorry that was a typo on my behalf, will update the previous post.

    The whole point of polymorphism is that you have a shared base type but cast it at runtime to be an inherited type.
    I wouldn't say that is "the whole point of polymorphism", but I know what you are getting at.

    Anyway, your second example will work just fine. A "B" can be passed to a function that takes an "A" and, through the "A" class interface, will still act like a B. Look at this program:

    Code:
        class A
        {
            public virtual string Name
            {
                get
                {
                    return "I'm an A";
                }
            }
        }
    
        class B : A
        {
            public override string Name
            {
                get
                {
                    return "I'm a B";
                }
            }
        }
    
        class Program
        {
            static void Main( string[ ] args )
            {
                B aB = new B( );
                A anA = new A( );
                PrintA( aB );       // workfs fine, prints "I'm a B".
                PrintB( anA );          // ERROR!  A is *not* a B, and it cannot be converted to one.            
            }
    
            static void PrintA( A a )
            {
                Console.WriteLine( a.Name );
            }
    
            static void PrintB( B b )
            {
                Console.WriteLine( b.Name );
            }
        }
    It *does* work. That is polymorphism, because the "B" still acts like a "B", but the function need only know that a "B" is a descendant of an "A". The other will not work. What if you add a new method to class "B" and try to call that method on something that is actually an "A"? That would not be possible, so there is no logical way to convert in that direction.

    Also, the "ref" argument is not needed. When you use the "ref" keyword, you are passing in the actual reference to the object, not a copy of one (C# passes references by value by default). So, unless you are changing what the referents points to, you do not need to use the "ref" keyword on reference types.
    Last edited by BigEd781; May 17th, 2009 at 05:33 PM.

  7. #7
    Join Date
    May 2007
    Posts
    1,546

    Re: Question about method with ref argument

    Code:
    class A { public int Var1; }
    class B : A { public int Var2; }
    
    class C
    {
        public static A GetB()
        {
            B Var = new B();
            generateA(ref Var);
        }
    
        protected static generateA(ref A Var)
        {
            Var = new A ();
        }
    }
    If you were allowed pass a 'B' location in this scenario, you can then put an 'A' where an 'A' cannot possibly exist. It's the direct equivalent of:

    B b = new A ();

    Which is obviously not allowed.
    www.monotorrent.com For all your .NET bittorrent needs

    NOTE: My code snippets are just snippets. They demonstrate an idea which can be adapted by you to solve your problem. They are not 100% complete and fully functional solutions equipped with error handling.

  8. #8
    Join Date
    Nov 2006
    Posts
    357

    Re: Question about method with ref argument

    Quote Originally Posted by BigEd781 View Post
    I wouldn't say that is "the whole point of polymorphism", but I know what you are getting at.

    Anyway, your second example will work just fine. A "B" can be passed to a function that takes an "A" and, through the "A" class interface, will still act like a B. Look at this program:

    Code:
        class A
        {
            public virtual string Name
            {
                get
                {
                    return "I'm an A";
                }
            }
        }
    
        class B : A
        {
            public override string Name
            {
                get
                {
                    return "I'm a B";
                }
            }
        }
    
        class Program
        {
            static void Main( string[ ] args )
            {
                B aB = new B( );
                A anA = new A( );
                PrintA( aB );       // workfs fine, prints "I'm a B".
                PrintB( anA );          // ERROR!  A is *not* a B, and it cannot be converted to one.            
            }
    
            static void PrintA( A a )
            {
                Console.WriteLine( a.Name );
            }
    
            static void PrintB( B b )
            {
                Console.WriteLine( b.Name );
            }
        }
    It *does* work. That is polymorphism, because the "B" still acts like a "B", but the function need only know that a "B" is a descendant of an "A". The other will not work. What if you add a new method to class "B" and try to call that method on something that is actually an "A"? That would not be possible, so there is no logical way to convert in that direction.

    Also, the "ref" argument is not needed. When you use the "ref" keyword, you are passing in the actual reference to the object, not a copy of one (C# passes references by value by default). So, unless you are changing what the referents points to, you do not need to use the "ref" keyword on reference types.
    Hey,

    Yeah, ive changed over to not using ref and works fine. However i thought it would work with ref anyway, but thats where my problems were coming from, trying to pass the reference type as a ref, but anyway problems solved i guess...

  9. #9
    Join Date
    Jun 2008
    Posts
    2,477

    Re: Question about method with ref argument

    The problem was not caused in any way by the 'ref' keyword, it would have worked just the same (but it was not needed).

  10. #10
    Join Date
    May 2007
    Posts
    1,546

    Re: Question about method with ref argument

    Quote Originally Posted by Grofit View Post
    Hey,

    Yeah, ive changed over to not using ref and works fine. However i thought it would work with ref anyway, but thats where my problems were coming from, trying to pass the reference type as a ref, but anyway problems solved i guess...
    At least you now understand *why* you couldn't pass it by ref. So you've learnt something new out of it aswell Though yes, 'ref' is completely unnecessary in this scenario.
    www.monotorrent.com For all your .NET bittorrent needs

    NOTE: My code snippets are just snippets. They demonstrate an idea which can be adapted by you to solve your problem. They are not 100% complete and fully functional solutions equipped with error handling.

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

Featured