【问题标题】:Return reference of generic泛型的返回引用
【发布时间】:2021-10-08 16:05:45
【问题描述】:

我怎样才能实现这样的目标?

public class BlaBlaBla
{
    private PotatoesContainer _containerField;
    private bool _booleanField;

    private ref T GetBackingFieldRef<T>(string propertyName)
    {
        if (string.IsNullOrWhiteSpace(propertyName))
            throw new ArgumentNullException(nameof(propertyName));

        if (propertyName == "BooleanProperty")
            return ref _booleanField;
        else if (propertyName == "ContainerProperty")
            return ref _containerField;

        throw new ArgumentException("Property does not exist", nameof(propertyName));
    }

    public void ManageProperty<T>(string propertyName, T newValue)
    {

        //Check stuff;

        var referenceToField = GetBackingFieldRef<T>(propertyName);

        referenceToField = newValue;

    }
}

我搜索了所有参考文档,但我看不到任何东西。而且我不能调用(T)

这可能吗?

还有其他方法吗(ActionFunc 之类的)?

【问题讨论】:

  • 只为提供的代码,尝试return ref (T)(object)_booleanField;:它有效吗?
  • @OlivierRogier 不,我试过了。
  • @OlivierRogier 我编辑了,添加了一些代码。
  • 泛型方法的重点是有一个方法,调用者可以提供他们想要的任何类型并且该方法将正常运行,而不是编写一个调用者需要提供完全正确类型的方法如果他们做任何其他事情,它就会中断。这种方法一开始就不应该是通用的。

标签: c# .net generics ref


【解决方案1】:

如果您使用不安全的代码,它是可行的(就像大多数事情一样)。我同意评论者的观点,即这是一个坏主意,并且有很多更好的方法可以实现您想要做的事情。但是出于教育目的,无论如何:

using System.Runtime.CompilerServices;

...

public unsafe ref T GetBackingFieldRef<T>(string propertyName)
{
    if (string.IsNullOrWhiteSpace(propertyName))
        throw new ArgumentNullException(nameof(propertyName));

    switch (propertyName)
    {
        case "BooleanProperty" when typeof(T) == typeof(bool):
            return ref Unsafe.AsRef<T>(Unsafe.AsPointer(ref _booleanField));
        case "ContainerProperty" when typeof(T) == typeof(PotatoesContainer):
            return ref Unsafe.AsRef<T>(Unsafe.AsPointer(ref _containerField));
        default:
            throw new ArgumentException("Property does not exist or type mismatch", nameof(propertyName));
    }
}

这使用Unsafe.AsPointer&lt;T&gt;()Unsafe.AsRef&lt;T&gt;() 来实现到ref T 的其他困难转换。有一些类型检查以确保 T 的类型与支持字段的类型匹配,但这当然非常脆弱 - 如果您更改支持字段的类型,您必须记住更改类型检查,并且必须手动查找对该字段的所有对 GetBackingFieldRef&lt;T&gt;() 的调用并更新它们,否则您将在运行时遇到异常和/或内存损坏。

【讨论】:

  • “还有很多更好的方法”,比如哪些?我太没有灵感了
  • @DrkDeveloper 您可以通过反射实现您的ManageProperty&lt;T&gt;(),如您问题的其中一个 cmet 中所述,但最终这与您最初在此处提出的问题不同。如果您遇到困难,我建议您尝试一下并发布一个新问题。
猜你喜欢
  • 1970-01-01
  • 2010-10-01
  • 2019-07-02
  • 1970-01-01
  • 2018-02-11
  • 1970-01-01
  • 2016-12-24
  • 2014-08-25
相关资源
最近更新 更多