gpt4 book ai didi

c# - 不使用 ref 关键字替换参数的 ref(使用 IL)

转载 作者:太空狗 更新时间:2023-10-30 00:34:45 25 4
gpt4 key购买 nike

我希望能够在不使用 ref 关键字的情况下替换参数的对象引用。

我避免使用 ref 的原因是为了保留查找 Add(T item) 方法的集合初始化程序调用,我需要让集合类用不同的实现替换引用它的界面。

我已经尝试了几种不同的方法来做到这一点。首先,我尝试使用未记录的关键字 __makeref__refvalue__reftype

其次,我尝试使用一些 IL 创建一个 DynamicMethod,它试图模仿我通过查看带有 ref 参数的反汇编类似调用所观察到的结果。

下面是一些代码来演示:

using System;
using System.Collections.Generic;
using System.Collections;
using System.Reflection.Emit;
using System.Reflection;
interface IRecord
{
string Name { get;}
}
class ImpA : IRecord
{
public string Name { get { return "Implementation A"; } }
}
class ImpB : IRecord
{
public string Name { get { return "Implementation B"; } }
}
class RecordList<T> : IEnumerable<T>
{
//// Standard Add method (of course does not work)
//public void Add(T item)
//{
// item = (T)(object)new ImpB();
//}

// ref method (works great but the signature cannot be
// used by the collection initializer)
public void Add(ref T item)
{
IRecord newItem = new ImpB();
item = (T)newItem;
}

//// Using System.TypedReference (does not work)
//public void Add(T item)
//{
// T newItem = (T)(object)new ImpB();
// TypedReference typedRef = __makeref(item);
// __refvalue(typedRef, T) = newItem;
//}

// Using Reflection.Emit DynamicMethod (This method should work but I need help)
public void Add(T item)
{
IRecord newItem = new ImpB();

System.Reflection.MethodAttributes methodAttributes =
System.Reflection.MethodAttributes.Public
| System.Reflection.MethodAttributes.Static;

DynamicMethod dm = new DynamicMethod("AssignRef",
methodAttributes,
CallingConventions.Standard,
null,
new Type[] { typeof(IRecord), typeof(IRecord) },
this.GetType(),
true);

ILGenerator generator = dm.GetILGenerator();
// IL of method
//public static void Add(ref item, ref newItem)
//{
// item = newItem;
//}
// -- Loading Params (before call to Add() --
//L_002b: ldloca.s sb // this is the ref variable
//L_002d: ldloc.2 // The other variable
// -- Add method IL --
//L_0000: nop
//L_0001: ldarg.0
//L_0002: ldarg.1
//L_0003: stind.ref
//L_0004: ret

generator.Emit(OpCodes.Ldarga_S, 0);
generator.Emit(OpCodes.Ldarg_1);
generator.Emit(OpCodes.Stind_Ref);
generator.Emit(OpCodes.Ret);

Action<IRecord, IRecord> AssignRef =
(Action<IRecord, IRecord>)dm.CreateDelegate(
typeof(Action<IRecord, IRecord>));

AssignRef((IRecord)item, (IRecord)newItem);
}


public IEnumerator GetEnumerator()
{
throw new NotImplementedException();
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
throw new NotImplementedException();
}
}
class Program
{
static void Main(string[] args)
{
IRecord imp = new ImpA();
Console.WriteLine("Original implementation: {0}\n", imp.Name);

// Calls Add Implicitly
RecordList<IRecord> records = new RecordList<IRecord> { imp };
// Prints "Implementation A"
Console.WriteLine("After Add Method: {0}", imp.Name);

records.Add(ref imp); // Explicit call with ref
// Prints "Implementation B"
Console.WriteLine("After Add Ref method: {0}\n", imp.Name);
}
}

谢谢。

最佳答案

I am looking to be able to replace the object reference of a parameter without having to use the ref keyword.

这根本不会发生;当您的 (non-ref) 方法被调用时,CLR 会创建您的方法接收的传递引用的副本。虽然您的方法可以根据其核心内容修改该引用,但无论您使用什么技巧,它都绝对无法访问从中创建副本的引用(调用方法传入的引用)尝试使用未记录的关键字或巧妙的 CIL。

此外,我不明白您为什么要尝试替换传递给集合初始值设定项的参数。它闻起来像是做了不该做的事情的代码。

关于c# - 不使用 ref 关键字替换参数的 ref(使用 IL),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6836682/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com