簡體   English   中英

C#:如何聲明多個相似的結構?

[英]C#: How to declare multiple similar structs?

我的應用程序使用了不同“類型”的幾個“句柄”(所有IntPtr)。

我想幫助確保將正確的句柄類型傳遞給我的各種方法...如果我使用IntPtr,則沒有提示該方法采用句柄類型A或句柄類型B.

如果L在C ++中,我可以使用typedef:

typedef uint32 HdlA;
typedef uint32 HdlB;

現在我有兩種類型,HdlA和HdlB,兩者都是通用U32的引擎蓋。 在C ++中,我也可以使用宏來聲明結構。

另外,出於編組的原因,我需要將它們作為值類型...不能使用類(當然,如果我可以使用可以解決所有問題的類)。

所有句柄的定義基本相同:

public struct HdlA
{
    private IntPtr _h;
    public bool IsValid             get { return (_h != IntPtr.Zero);} }
    //public HdlA()                 { _h = IntPtr.Zero; } // C# disallows arg-less ctor on struct
    public HdlA(IntPtr h)           { _h = h; }
    public void Invalidate()        { _h = IntPtr.Zero; }
    public static implicit operator IntPtr(HdlA hdl)  { return hdl._h; }
}
public struct HdlB
{
    private IntPtr _h;
    public bool IsValid             get { return (_h != IntPtr.Zero);} }
    //public HdlB()                 { _h = IntPtr.Zero; } // C# disallows arg-less ctor on struct
    public HdlB(IntPtr h)           { _h = h; }
    public void Invalidate()        { _h = IntPtr.Zero; }
    public static implicit operator IntPtr(HdlB hdl)  { return hdl._h; }
}
... etc ...

我當然可以做到這一點 - 我可以聲明5或6個相同的代碼塊,其中只有結構名稱變化 - 但這不是很優雅。

我考慮過使用一個接口,但不允許成員字段,所以沒有運氣。

我喜歡的是擁有一個基礎結構然后讓HdlA,HdlB等簡單地從基礎派生出來。 但C#不允許結構中的基類型。

這似乎應該有一個簡單而優雅的解決方案,但它逃避了我:(

有任何想法嗎?

一種解決方案是僅使用一個包含所有公共字段的結構,並添加一個字段(int或Enum),以顯示要使用的結構的類型。 當然,如果您能夠使用類,那么您將使用繼承,但在這種情況下,添加HandleType字段可以解決問題。

然后,您可以檢查每個方法中的該字段,以查看是否已傳遞正確的結構。

你沒有在你的問題中提供大量的背景,所以我在黑暗中瘋狂地刺傷。

可能使用類在您的情況,畢竟。 聲明抽象基類,從中派生HndlA和HndlB,並在基類上提供ToHandle()方法,將類轉換為結構。 ToHandle()的值將是您編組的對象。

再次,只是在黑暗中瘋狂地刺傷。

在C ++中,我也可以使用宏來聲明結構。

在C#中,您可以使用T4模板

或嚴格來說,它不是C#本身,雖然它可以使用C#作為腳本語言和輸出,並且它可以構建在C#(VisualStudio,MonoDevelop,SharpDevelop,Nant)的幾乎任何構建工具中。只是調用編譯器本身。

創建一個擴展名為.tt.t4的文件,如:

<#@ template language="C#" #>
<#@ output extension=".generated.cs" #>
namespace SomeNamespace
{
<#
foreach(string name in new string[]{"HdlA", "HdlB", /*… and so on… */})
{#>
    public struct <#=name#>
    {
        private IntPtr _h;
        public bool IsValid
        {
            get { return (_h != IntPtr.Zero); }
        }
        public <#=name#>(IntPtr h)
        {
            _h = h;
        }
        public void Invalidate()
        {
            _h = IntPtr.Zero;
        }
        public static implicit operator IntPtr(<#=name#> hdl)
        {
            return hdl._h;
        }
    }
<#}#>
}

它的工作原理與ASP.NET相同,但會生成本地文件。 在這里,我們使用它來生成一個.cs文件,然后它將成為編譯的一部分,必要時首先重建.cs文件。 唉,雖然它是一個生成的文件,如果你沒有將它包含在你的源代碼控制中,它會引起問題(必須啟動一個關於這種煩惱的問題)。

是我的一個真實的例子,它更加真實。 這里不是想要使用不同名稱的類似類,而是希望使用不同類型的不同方法,但這是相同的基本原則。

順便說說,

// C#不允許在struct上使用arg-less ctor

根據你如何看待它,你也可以說它堅持你必須有一個預定義的無arg零填充構造函數,你不能擺脫或替換([通常]沒有這樣的方法,但我們在調用C#中使用new blah() )。 雖然在.NET中可以做到這一點,但是在調用它或發生零填充的情況下的差異導致足夠的混淆,堅持構造函數匹配零填充確實可以節省一些問題。

暫無
暫無

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

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