使用对通用对象的引用作为参数

时间:2009-10-13 07:07:08

标签: c# .net generics

我在传递对泛型类型的对象的引用时遇到了一些麻烦。我找到了一种方法,创建一个'对象'并传递一个引用而不是原始的 - 但它似乎闻到了一点我。这里有更好的方法,还是我必须忍受它?

我理解第一个错误,但第二个错误让我失望。

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不是通用的,因为它使用Obj类型可以改变的递归。我试图不使用反射来调用它的泛型版本,虽然在发布时可能会有更好的选择吗?

3 个答案:

答案 0 :(得分:5)

ref参数的类型应与参数的类型匹配。您不能在此处依赖隐式转换。 Eric Lippert有一篇相关的博文:Why do ref and out parameters not allow type variation?

答案 1 :(得分:3)

第二条错误消息已包含解释:

  

ref或out参数必须是可赋值变量

就是这样:通过强制转换创建新对象(Object) bar可以引用相同的底层对象,但它仍然是一个不同的值。此外,它是临时值,因为您从未将其分配给不同的变量名称。因此,通过引用传递它是没有意义的 - 对该临时对象的任何更改都将丢失。因此,临时性是严格的右值:你不能分配它们,或通过引用传递它们。

这也是你的第三个代码有效的原因:你现在已经将转换的结果绑定到一个新名称,这个名字可以用作左值,即它可以被改变(分配给,通过引用传递)。

答案 2 :(得分:0)

对于第二个示例,您需要首先将其强制转换为对象变量:

object obj = (object)Bar;
Result = (T)ModifyObject (ref obj);

但是在执行该方法之后,唯一可以肯定的是obj将是Object类型。这就是编译器警告你的事情。

代码 闻到了一点味道。如果要返回类型为T的结果,那么我没有看到通过引用传递参数的原因。其次,您不需要通过引用传递类型的实例来创建它。这种方法可以正常工作:

public static Object DoSomething(Type objType) {
    Object Result = Activator.CreateInstance(objType)
}

最后,如果你使用泛型,那么就没有理由进行所有的转换。 正是为什么您正在使用通用参数,以使您的类成为不同类型的模板。