5

In c# I am trying to implement a method which I can use to bind data to any control I pass to it (provided of course the control is derived from a databoundcontrol object)

given the method

 public void CTLBindData(ref DataBoundControl ctl){ ... }

I get an error when trying to pass derived control to the function
for example the following code

DropDownList lister = new DropDownList();  
CTLBindData(ref lister);

Generates a conversion error

Ok I can accept that, but the following confuses me (probably because I am used to c++ not c#)

CTLBindData(ref (DataBoundControl)lister);

in this case I get the error "A ref or out argument must be an assignable variable"

For clarification A Dropdownlist inherits from a list control which inherits from a DataBoundControl

This makes no sense to me I should be able to pass in any object that has been derived from a databound control. It seems that the explicit typecast is causing the problem.

Any clues as to what I am doing wrong?

DC

3
  • The answer of @Andrew is correct, but, are you sure it has to be passed by ref? Logically, you may get back different object of different type. If you're not going to assign it with new object inside CTLBindData there is no difference between passing it with and without ref.
    – Elisha
    Commented Nov 3, 2009 at 5:12
  • Are you saying that c# defaults to passing objects as refs not values? To me its not logical that you can get back a different object, unless refs are closer to pointers than actual references. Commented Nov 3, 2009 at 5:28
  • Using ref is what would allow a different object to come back. If you read the link in my answer, it explains it far better than any of us can in a comment. Commented Nov 3, 2009 at 5:38

4 Answers 4

7

Do the cast prior to calling the method like this:

DataBoundControl countrol = (DataBoundControl)lister;
CTLBindData(ref control);

C# requires that any ref parameters be of the exact type (no polymorphism) and the reference of that type must be assignable. This is why you must create the reference via explicit cast in a separate step so the method has a reference of the correct type to which a value can be assigned.

For more information about this topic please see Why do ref and out parameters not allow type variation? by Eric Lippert:

If you have a method that takes an "X" then you have to pass an expression of type X or something convertible to X. Say, an expression of a type derived from X. But if you have a method that takes a "ref X", you have to pass a ref to a variable of type X, period. Why is that? Why not allow the type to vary, as we do with non-ref calls?

4
  • Isn't this making a copy of the control and losing its Listbox class or does DataBoundControl countrol = (DataBoundControl)lister; create a reference to the control? Commented Nov 3, 2009 at 5:39
  • 1
    You are simply creating a copy of the reference, not a copy of the control itself. The new reference points to the same exact objects and no conversion is taking place. Commented Nov 3, 2009 at 5:43
  • I think I get it now. in c# the assignment (=) operator creates a reference to an object unlike say c++ where it makes a copy of the object If you want a reference in c++ you must specify the & operator Commented Nov 3, 2009 at 5:56
  • @DeveloperChris - Correct, in C# you don't work directly with pointers in managed code. Commented Nov 3, 2009 at 6:06
2

Use a generic function with the appropriate type parameter constraint:

public void CTLBindData<TControl>(ref TControl ctl)
    where TControl : DataBoundControl 
{ ... }

The type is inferred directly in the call, and the ocnstraint ensures that the control is of the appropriate type.

0

Andrew Hare is correct, but in this case, you may not even want to be using the ref. Objects in C# are already passed by reference*. (As opposed to value types, which are not passed by reference unless you use the ref keyword.) There are very few cases that I can think of where you'd actually need to pass a reference type in that way. Without the ref, your original code should work just fine.

**Not really, but it's easier to understand that way if you come from a non-C# background. The reference is actually passed by value. There is an excellent article on the exactly how this all works.*

2
  • 1
    While I agree that ref is probably not needed here it is important to make the distinction that objects are not passed by reference. Rather object references are passed by value. Commented Nov 3, 2009 at 5:26
  • Indeed. I added that clarification to my answer. Commented Nov 3, 2009 at 5:26
0

Andrew Hare answered very well.

Your object must need something inside to use REF or OUT. For example: could be null.

DropDownList lister = new DropDownList();
lister = null;   
CTLBindData(ref lister);

Not the answer you're looking for? Browse other questions tagged or ask your own question.