[英]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.