【问题标题】:Alternative to using Func to return a Span<T> or other ref struct [duplicate]替代使用 Func 返回 Span<T> 或其他 ref struct [重复]
【发布时间】:2018-03-07 04:40:56
【问题描述】:

如何将返回 Span 的方法作为参数传递?

using System.Memory;   
public Span<byte> CallSpanFactory1(Func<Span<byte>> spanFactory)
{
    return spanFactory();
}

此代码返回错误“类型 'Span' 可能不能用作类型参数”(这是有道理的,因为使用 ref 结构作为泛型类型参数可能会导致装箱,因此被禁止)。

【问题讨论】:

  • 正如@Servy 所指出的,答案类似于问题stackoverflow.com/questions/2462814/… 的答案,但该问题并不直接。首先,Span 可以作为不带 ref 关键字的参数传递,并且委托可以省略 ref 关键字。其次,产生的错误与错误不同。第三,该问题不涉及返回 ref struct 或其他 ref 值。使用 Func>,span 由函数返回。
  • 好点@Servy,但这不是关于“通过引用传递值的委托”。 ref 结构并不总是通过引用传递。如果 RS 是 ref struct 类型,则方法 A(ref RS x) 与 A(RS x) 不同。此外,这也是一个关于返回 ref struct 值的委托的问题。这也是一种不同的野兽。用于解决问题的技术是相同的,但问题是不同的。
  • 这些页面表面上相似,答案的三个单词版本是“使用委托”,但挑战不同(返回 ref 结构与通过引用传递对象),问题的原因是不同的(即使它被值使用,也不能将 ref 结构作为通用参数,因为它不能装箱与不能有 ref 泛型参数),因此答案也不同(没有“ref” , 变量由委托返回)。因此,您将用户从具有正确答案的页面绕道到可以通过类比收集答案的页面。
  • 公共委托对象 MethodNameDelegate(ref float y);与公共委托 Span MethodNameDelegate(); 不同。当您想要通过引用传递参数时委托工作并不意味着当您想要返回 ref 结构时委托将工作。 C# 7.2 的设计者对何时以及如何返回 ref 结构做出了具体决定(goo.gl/pJcNHi),因此其他页面上的代码是否解决了相同的问题或者对该代码的更改是否会起作用并不明显。因此,更准确的答案对用户更有帮助。
  • @Servy 在这一点上,我们可能正在互相交谈,应该停止。下面发布的答案包含与另一页上的代码不同的代码。委托返回一个 Span。它没有 ref 参数。您关于以下答案“不包含该答案中未找到的任何信息”的说法是错误的。语法不一样!但我理解并尊重您的观点,即让程序员根据另一页上语法略有不同的类似代码找出下面的具体答案会更好。

标签: c# html system.memory


【解决方案1】:

这是一种必须使用委托而不能使用 Func 或 Action 的情况。

using System.Memory;
public delegate Span<byte> SpanFactoryFunc();

public Span<byte> CallSpanFactory(SpanFactoryFunc spanFactory)
{
    return spanFactory();
}

在其他情况下,由于泛型类型参数的限制,必须使用委托。 This question 标识了一种这样的情况——希望将包含通过引用传递的参数的方法作为参数传递。这不能用 Func 或 Action 来实现,因为没有 ref 泛型类型参数之类的东西。没有像Func&lt;ref float, object&gt; 这样的语法。

这里对泛型类型参数的限制是不同的:即使没有“ref”修饰符,也没有像Func&lt;MyRefStruct&gt;Func&lt;MyRefStruct, object&gt; 这样的语法。这不是因为MyRefStruct 将始终通过引用隐式传递。 Ref 结构并不总是通过引用隐式传递。它们可以通过引用或值传递。同样,ref struct 并不总是作为“ref 返回”返回。

因此,委托的形式很重要——以下两个委托将产生不同的效果:

public ref struct MyRefStruct
{
    // ...
}

public delegate void MyRefStructMutator(ref MyRefStruct s); // s is passed by reference
public delegate void MyRefStructAction(MyRefStruct s); // s is passed by value

请注意,如果我们使用 struct 或称为 MyTypeclass 而不是 ref struct MyRefStruct,则不需要类似于 MyRefStructAction 的委托;可以简单地使用Action&lt;MyType&gt;。同样,可以使用Func&lt;MyType&gt; 返回 MyType。只有ref structs 的出现,在传递按值传递参数或按值返回的方法时,才需要使用委托。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-28
    • 1970-01-01
    • 2022-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-24
    • 1970-01-01
    相关资源
    最近更新 更多