簡體   English   中英

使用 Struct 作為通用參數並轉換到基接口會導致錯誤:必須是不可為空的值類型

[英]Using Struct as Generic Parameter and casting to the base interface cause the error: must be a non-nullable value type

我需要創建一個 ConcreteProviderX 實例的集合來在它上面執行 LINQ 操作符。 我更喜歡將 struct 用於 ConcreteArgumentsX 類型,但在創建數組時強制轉換為基接口 IArguments 會導致編譯時錯誤:類型“IArguments”必須是不可為空的值類型,以便將其用作參數“T”泛型類型或方法“ICommandProvider”(代碼 = CS0453)。 對於 ConcreteArgumentsX 類型,我有一個使用類而不是結構的替代實現,但它會導致運行時 System.InvalidCastException(無法將“SetProvider”轉換為“ICommandProvider”)。 對於 struct 的情況和 class 的情況,錯誤將如何解決?

namespace ErrorUsingStructForConcreteArgumentsX
{
    interface ICommandProvider<T> where T : struct, IArguments
    {
        void F(string command, out T? arguments);
    }

    class ConcreteProvider1 : ICommandProvider<ConcreteArguments1>
    {
        public void F(string command, out ConcreteArguments1? arguments) { arguments = null; /* other code */ }
    }

    class ConcreteProvider2 : ICommandProvider<ConcreteArguments2>
    {
        public void F(string command, out ConcreteArguments2? arguments) { arguments = null; /* other code */ }
    }

    interface IArguments { }
    struct ConcreteArguments1 : IArguments { /* some value type properties */ }
    struct ConcreteArguments2 : IArguments { /* some value type properties */ }

    class Program
    {
        static void Main(string[] args)
        {
            ICommandProvider<ConcreteArguments1> provider = new ConcreteProvider1(); // ok

            // compile-time error
            var providers = new ICommandProvider<IArguments>[]
            {
                (ICommandProvider<IArguments>)new ConcreteProvider1(),
                (ICommandProvider<IArguments>)new ConcreteProvider2()
            };
        }
    }
}

namespace AlternativeUsingClassForConcreteArgumentsX
{
    interface ICommandProvider<IArguments>
    {
        void F(string command, out IArguments arguments);
    }

    class ConcreteProvider1 : ICommandProvider<ConcreteArguments1>
    {
        public void F(string command, out ConcreteArguments1 arguments) { arguments = null; /* other code */ }
    }

    class ConcreteProvider2 : ICommandProvider<ConcreteArguments2>
    {
        public void F(string command, out ConcreteArguments2 arguments) { arguments = null; /* other code */ }
    }

    interface IArguments { }
    class ConcreteArguments1 : IArguments { /* some value type properties */  }
    class ConcreteArguments2 : IArguments { /* some value type properties */ }

    class Program
    {
        static void Main(string[] args)
        {
            ICommandProvider<ConcreteArguments1> provider = new ConcreteProvider1(); // ok

            // runtime error
            var providers = new ICommandProvider<IArguments>[]
            {
                (ICommandProvider<IArguments>)new ConcreteProvider1(),
                (ICommandProvider<IArguments>)new ConcreteProvider2()
            };
        }
    }
}

struct是值類型,而IArguments是引用類型。 引用類型是NULLable ,但是值類型不是NULLable 由於通用約束總是“AND”,這意味着您的T應該滿足您的where語句中寫入的所有條件 - where T : struct, IArguments 所以這就是你出錯的原因:

類型“IArguments”必須是不可為空的值類型,以便將其用作泛型類型或方法“ICommandProvider”中的參數“T”

更新:

也許這個實現會很有用:

static void Main(string[] args)
{
    ICommandProvider<IArguments> provider = new ConcreteProvider1();
    var providers = new ICommandProvider<IArguments>[]
    {
        new ConcreteProvider1(),
        new ConcreteProvider2()
    };
}

其他代碼如下所示:

interface ICommandProvider<T> where T : IArguments
{
    void F(string command, T arguments);
}

class ConcreteProvider1 : ICommandProvider<IArguments>
{
    public void F(string command, IArguments arguments)
    {
        throw new NotImplementedException();
    }
}

class ConcreteProvider2 : ICommandProvider<IArguments>
{
    public void F(string command, IArguments arguments)
    {
        throw new NotImplementedException();
    }
}

interface IArguments { }
class ConcreteArguments1 : IArguments { /* some value type properties */ }
class ConcreteArguments2 : IArguments { /* some value type properties */ }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM