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