研究Int32&的时候,无意中发现C#里面还有4个Undocument Keyword, 分别是__makeref, __reftype, __refvalue 以及__arglist。 其中前三个keyword可以这样用:

        int i = 1;
        
        TypedReference tr 
= __makeref(i);
        Type t 
= __reftype(tr); //t = System.Int32
        
        
int i1 = __refvalue(tr, int); //i1 = 1
        int i2 = (int)TypedReference.ToObject(tr); //i2 = 1
        
        i
++//i = 2
        
        
int i3 = __refvalue(tr, int); //i3 = 2

(关于TypedReference类型MSDN是这样描述的:Describes objects that contain both a managed pointer to a location and a runtime representation of the type that may be stored at that location. 同时TypedReference有[CLSCompliant(false)]标记)

于是我们可以用下面这种方法来模拟ByRef的参数

public class MyClass
{
    
public static void Main()
    
{
        
int v = 99;
        TypedReference trParameters 
= __makeref(v);
        Foo(trParameters);

        Console.WriteLine(
"v = {0}", v); // v = 100 
    }

    

    
public static void Foo(TypedReference tr)
    
{
        
if(__reftype(tr) == typeof(int))
        
{
            __refvalue(tr, 
int)++;
        }

    }

}

比较不爽的就是我们必须在Foo方法体中判断TypedReference包含的类型。

注意如果把Foo写成public static void Foo(ref TypedReference tr),编译器会抱怨说:Method or delegate parameter cannot be of type 'ref System.TypedReference'。

至于__arglist则可以模拟params关键字,抄个例子:

public void Function(__arglist) 
{
    ArgIterator iterator 
= new ArgIterator(__arglist);
    
for (int count=iterator.GetRemainingCount(); count>0; count--)
    
{
        TypedReference typedRef 
= iterator.GetNextArg();
        Console.WriteLine(__refvalue(typedRef, 
int));
   }

}

调用它:Function(__arglist(2,3,4));  输出2,3,4

后注:这4个keyword毕竟是undocument的,微软也没有提供任何支持,所以不排除以后被delete掉。Mono下面的编译器似乎也不支持,不过我在vs2005 beta里面试验还是有效的。

 Updated: Flier Lu在他的blog对__arglist的使用作了更深入的探讨,推荐阅读。 :)