可以转换为接口,但不能转换为泛型

Can cast to interface, but not to generic type

TL;DR: 1) 我的代码的非泛型版本允许我将对象转换为我知道它实现的接口;一个通用版本,我在其中转换为通用类型,将无法编译。我是否缺少一个约束 and/or 解决方法? 2) 如果 C# 不支持我正在做的事情,是否有其他方法可以实现我更广泛的目标?

我最接近发现与我自己的问题类似的问题是 this,其中唯一的答案是“这没有任何意义,因为它不会导致 [原文如此] 受到任何限制。”那么,让我详细说明我面临的确切限制...

这是我的代码的非通用版本;希望内联评论能解释我正在尝试做什么,以及为什么:

public interface ISomeInterface
{
    string SomeFxn();
}

[Serializable]
public class SerializableInterfaceReferenceForUnity
{
    // Unity has long been able to serialize references to its own objects, but using this 
    // attribute on a "raw C#" object (i.e., anything other than Object) would try to
    // serialize the **value**.
    [SerializeField] private UnityEngine.Object unityObj;

    // This new(-ish) attribute actually allows us to serialize references ... but ONLY to
    // "raw C#" objects!  (If rawObj is a UnityEngine.Object that implements 
    // ISomeInterface, I get error messages in the console.)
    [SerializeReference] private ISomeInterface rawObj;

    // So, a kludge: branching my logic based on the type that implements ISomeInterface.
    [SerializeField] private bool objIsUnityType;

    // In my defense, I *think* the kludge will be entirely hidden on the back-end;
    // the API will "just work":
    public ISomeInterface obj
    {
        get
        {
            // FLAG: this next line works here, but breaks in generic version
            if (objIsUnityType) { return (ISomeInterface) unityObj; }
            else { return rawObj; }
        }
        set
        {
            switch (value)
            {
                case UnityEngine.Object uo:
                {
                    objIsUnityType = true;
                    unityObj = uo;
                    rawObj = null;
                    return;
                }
                default:
                {
                    objIsUnityType = false;
                    rawObj = value;
                    unityObj = null;
                    return;
                }
            }
        }
    }
}

以上都很好,但真正的目标是允许我序列化 Unity 中的任何界面。所以,这是一个通用版本......它是相同的行,除了 ISomeInterface 变成 TSomeInterface:

[Serializable]
public class SerializableInterfaceReferenceForUnity<TSomeInterface> 
// where TSomeInterface : { what goes here?! }
{
    [SerializeField] private UnityEngine.Object unityObj;
    [SerializeReference] private TSomeInterface rawObj;
    [SerializeField] private bool objIsUnityType;
    public TSomeInterface obj
    {
        get
        {
            //"CS0030 Cannot covert type 'UnityEngine.Object'
            // to 'TSomeInterface'" on the below:
            if (objIsUnityType) { return (TSomeInterface) unityObj; } 
            else { return rawObj; }
        }
        set
        {
            switch (value)
            {
                case UnityEngine.Object uo:
                {
                    objIsUnityType = true;
                    unityObj = uo;
                    rawObj = default;
                    return;
                }
                default:
                {
                    objIsUnityType = false;
                    rawObj = value;
                    unityObj = null;
                    return;
                }
            }
        }
    }
}

我祈祷我所需要的只是对泛型类型的约束。

除此之外,是否有任何变通方法(例如,一些反射魔法)将任意对象更改为(通用)接口类型?

除此之外,是否有任何方法可以实现相同的 objective(即对实现给定接口的对象的引用的 Unity 序列化,无论这些对象是否是 Unity 内置的- ins 或原始 C#) 以一种干净的方式?

也欢迎反馈/烂番茄关于我的kludge。

我对Unity一无所知,但假设UnityEngine.Object是一个引用类型,那么你应该可以这样做:

public class SerializableInterfaceReferenceForUnity<TSomeInterface> 
       where TSomeInterface : class
{
    public TSomeInterface obj
    {
        get
        {
            if (objIsUnityType) { return unityObj as TSomeInterface; } 
            else { return rawObj; }
        }
}

唯一要记住的是,您将无法使用任何值类型 (struct) 作为您的 SerializableInterfaceReferenceForUnity class.