【问题标题】:Practical uses of TypedReferenceTypedReference 的实际使用
【发布时间】:2009-11-10 21:36:50
【问题描述】:

TypedReference 结构是否有任何实际用途,您会在实际代码中实际使用?

编辑:.Net 框架在Console.WriteLineString.Concat 的重载中使用它们,它们从__arglist 参数构建一个数组并将其传递给正常的params 重载。为什么会存在这些重载?

【问题讨论】:

  • 为什么这不是建设性的? :o
  • 您也可以使用它来传递堆栈位置/变量引用“周围”(例如,传递给其他线程或从方法返回)。它需要不安全的代码并将 TypedReference “复制”为两个 IntPtr。

标签: c# .net typedreference


【解决方案1】:

TypedReference 结构体有什么实际用途,您会在实际代码中实际使用吗?

是的。如果我需要与 C 风格的可变参数方法的互操作性,我会使用它们。

为什么会存在这些重载?

它们的存在是为了与喜欢使用 C 风格的可变参数方法的调用者进行互操作。

【讨论】:

  • +1 表示不要抨击 C 风格的可变参数位 :) 希望您在 5.0 之前拥有可变参数模板(不是泛型)。
【解决方案2】:

这似乎是一个非常古老的问题,但我想再添加一个用例:当您有一个结构并希望通过反射设置其变量时,您将始终对装箱值进行操作并且永远不会改变原本的。这是没用的:

TestFields fields = new TestFields { MaxValue = 1234 };
FieldInfo info = typeof(TestFields).GetField("MaxValue");
info.SetValue(fields, 4096);

// result: fields.MaxValue is still 1234!!

这可以通过隐式装箱来解决,但是你会失去类型安全性。相反,您可以使用 TypedParameter 解决此问题:

TestFields fields = new TestFields { MaxValue = 1234 };
FieldInfo info = fields.GetType().GetField("MaxValue");

TypedReference reference = __makeref(fields);
info.SetValueDirect(reference, 4096);

// result: fields.MaxValue is now indeed 4096!!

【讨论】:

  • 我不知道我是否会将此称为反射特定问题。 SetValue 将对象作为输入,因此任何值类型都将被装箱以匹配方法的签名。
  • @BrianRasmussen:afaik,这种反射特定的行为源于反射早于泛型,否则不需要装箱。在(预)装箱的值类型和引用上不会出现这个问题。
  • 我的意思是,任何将object 作为输入的方法(在您的示例中SetValue 的第一个重载就是这样做的)都会强制将值装箱。这就是统一类型系统处理值的方式。这并不特定于反射。
  • 是的,然后系统引入了ref 来处理值引用,但是 SetXXX 没有引用重载。确实,系统是这样设计的,这难道不是他们添加SetValueDirect 并因此不得不引入一个既是值的引用又是对象的对象的唯一原因?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-21
  • 2011-10-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-10
相关资源
最近更新 更多