Tech Off Thread

5 posts

Reference Parameters in C#

Back to Forum: Tech Off
  • User profile image
    CGuy

    Hi everyone

    I'm wondering why C# was designed to not implicitly downcast parameters declared references to the designated type as stated in 10.5.1.2 in the spec. For example, consider the following code...

    public interface IFooBar
    ...

    public class FooBar : IFooBar
    ...

    public class Foo
    {
       public void Bar(ref IFooBar fooBar)
       ...
    }

    ...

    // The call.
    FooBar myFooBar = ...
    foo.Bar(ref myFooBar);

    This call fails because a ref FooBar is not the same as a ref IFooBar. I am surprised by this feature of C# and wonder why the decision was made to not support implicit downcasting such as with value parameters.

    Interestingly enough, it is quite acceptable to the language specification for me to do the following...

    // The call.
    ...
    IFooBar myIFooBar = myFooBar;
    foo.Bar(ref myIFooBar);

    Could anyone shed some light as to why it was decided not to support implicit reference parameters?

    Thanks in advance.

    Regards
    Glenn

  • User profile image
    AT

    Trivial.  C# params by default are "in" params you pass reference to existing object and downcast allowed, also you can use "out" specifier to specify that you expect value returned and well you can use "ref" to specify that value is both in and out.

    In case if you have IFooBar then you can downcast to IFoo then pass as input param, but IFoo object returned from method can not casted to IFooBar sub-class.

    Check out this tiny example to understand why:

    interface IFoo { }
    class IFooBar : IFoo { }
    class IFooClub : IFoo { }

    class Program
    {
        void DoFoo(ref IFoo param) {
            Random r = new Random();
            if (r.Next() % 2 == 0)
             param = new IFooClub();  
            else
             param = new IFooBar(); 
        }
        void DoFooMagic()
        {
            IFooBar myFoo = new IFooBar();
            DoFoo(ref myFoo); // <-- Error it can be IFooClub too ;o)), 
                              //Need to save as IFoo and check return type 
        }
    }

  • User profile image
    CGuy

    Thanks for your reply AT.

    Interesting code example: however, that isn't my intention using this code. I simply want to have DoFoo modify my IFooBar using methods exposed by the IFoo interface. Once that has happened, I examine the changes DoFoo made.

    Something like this:

    interface IFoo { void Modify(); }
    class IFooBar : IFoo
    {
       public void Modify() {...}
       public bool WasModified {...}
    }
    class Program
    {
       void DoFoo(ref IFoo param)
       {param.Modify();}
       
       void DoFooMagic()
       {
          IFooBar myFoo = new IFooBar();
          DoFoo(ref myFoo);
          if (myFoo.WasModified)
             ...
       }
    }

    As you can see, the parameter remains intact throughout the operation and the modifications are reflected outside the class. Also note that outside of DoFoo I interact with IFooBar's interface extensions, namely WasModified.

    Is there any other way to express this same intent without having to write specialisations for each possible type?

    Thanks

    Regards
    Glenn

  • User profile image
    BenDi

    If you only want to call methods on an existing object, there is no need to pass it as 'ref'.

    void DoFoo(IFoo param)
       {param.Modify();}

    will work just fine. And there you will have downcasting.

    Cheers

    Ben

  • User profile image
    CGuy

    Thanks for your response, Ben.

    I see what you mean. I guess ref isn't needed because Foo is a reference type.

    Thanks again.

    Regards
    Glenn

Comments closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums, or Contact Us and let us know.