繁体   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