Reputation:
I am having some troubles passing a reference to an object which is of generic type. I have found a way around by creating a 'Object' and passing a reference to that rather than the original - but it seems to smell a bit to me. Is there a better way here or do I have to live with it?
I understand the first error but the second eludes me.
public static T Foo<T>(ref T Bar)
{
T Result;
// Next line gives
// cannot convert from 'ref T' to 'ref object'
Result = (T)ModifyObject (ref Bar);
// Next line gives
// A ref or out argument must be an assignable variable
Result = (T)ModifyObject (ref ((Object)Bar) );
// Works
Object Tmp = Bar;
Result = (T)ModifyObject (ref Tmp) );
return Result;
}
public static Object DoSomthing(ref Object Obj) {
Object Result = Activator.CreateInstance (Obj.GetType ())
//...
}
DoSomething is not generic as it uses recursion where the type of Obj can change. I was trying to stick away from using reflection to call a generic version of it, although on posting maybe it would be a better option?
Upvotes: 5
Views: 9600
Reputation: 421978
The type of a ref
argument should match the type of the parameter. You cannot rely on implicit conversions here. Eric Lippert has a related blog post: Why do ref and out parameters not allow type variation?
Upvotes: 5
Reputation: 51214
For the second example, you will need to cast it to an object variable first:
object obj = (object)Bar;
Result = (T)ModifyObject (ref obj);
But after the method is executed, the only thing that is sure is that obj
will be of type Object
. That is what compiler is warning you about.
And the code does smell a bit. If you are returning a result of type T, then I don't see a reason to pass the parameter by reference. Second thing, you don't need to pass an instance of your type, by reference, in order to create it. This method would work just fine:
public static Object DoSomething(Type objType) {
Object Result = Activator.CreateInstance(objType)
}
And finally, if you are using generics, then there should not be a reason to do all the casting. That is exactly why you are using a generic parameter, to make your class a template for different types.
Upvotes: 0
Reputation: 545568
The second error message already contains an explanation:
A ref or out argument must be an assignable variable
That’s it: you create a new object by casting: (Object) bar
may reference the same underlying object but it’s a different value nonetheless. Furthermore, it’s a temporary value because you never assigned it to a distinct variable name. Thus, passing it by reference is meaningless – any change to that temporary object would be lost. Thus, temporaries are strictly rvalues: you cannot assign to them, or pass them by reference.
This is also why your third code works: you’ve now bound the result of the conversion to a new name and this name can be used as an lvalue, i.e. it can be changed (assigned to, passed by reference).
Upvotes: 3