gpt4 book ai didi

C#类实例属性机制

转载 作者:行者123 更新时间:2023-11-30 22:12:53 24 4
gpt4 key购买 nike

在 C# 中是否有一种明智的方法来实现以下构造(伪代码):

void Method(MyClass<Attribute1, Attribute2, ...> foo)
{
// here I am guaranteed that foo has the specified attributes
}

例如,Attribute* 是枚举值,这样只有使用方法所需属性实例化的 MyClass 实例才能传递给方法(并且否则无法编译)?

我尝试查看泛型,因为我知道 C++ 模板可以完成这项工作,所以它看起来像是一个合乎逻辑的起点,但我无法让它优雅地工作(我尝试使用接口(interface)来约束参数的类型时尚,但它非常笨重,坦率地说无法使用,因为我至少有 4 个属性)。

我想这样做是为了避免在每个方法的开头进行大量烦人的检查。我正在做 DirectX 11 图形开发,所以我有点受 API 的限制,这并不能使以这种“类型安全”的方式传递对象变得特别容易(在 DirectX 中,每个资源都有一个很大的“描述”结构,其中包含信息关于资源可以做什么和不能做什么,是什么不是等等。而且解析起来很乏味且容易出错,所以为了我和我的用户的方便,我试图围绕它编写一个包装器)。

我也不能为每种情况使用不同的类类型,因为有很多组合,所以这似乎是编写此类代码的最舒适方式,我希望 C# 能够实现这一点。


我确定这种语言功能有一个名称(如果您知道请告诉我,我会用谷歌搜索,但是当您不知道正确的关键字时很难搜索到。 ..)

最佳答案

.NET 中的泛型类型参数本身必须是类型。您不能创建仅特定于泛型类型参数的特定值的泛型类型/方法。

如果您不想或不能创建一个表示您希望将方法限制到的属性值的类型,则必须在您的方法中进行健全性检查以确保在提供的“foo”中使用正确的属性值"对象。


使用特定类型作为特定属性值的表示可能是您所问问题的答案,但它的缺点是不支持 switch-case 语句(请参见下文)。另请阅读我的回答末尾的最后注释。

比如说,您想要一个表示纹理的类型。纹理可以有不同数量的 channel 和不同的位深度。然后您可以像这样声明一个通用纹理类型:

class Texture<TChannels, TBPC>
where TChannels : INumOfChannels,new()
where TBPC : IBitsPerChannel,new()

INumOfChannelsIBitsPerChannel 只是接口(interface),可以为空。
new() 约束阻止使用接口(interface)本身创建具体的纹理类型。

对于不同的 channel 和不同的 BPC,您将创建从各自的基础接口(interface)扩展的空类型,例如:

class FourChannels : INumOfChannels {};
class ThreeChannels : INumOfChannels {};

class BitsPerChannel_24 : IBitsPerChannel {};
class BitsPerChannel_32 : IBitsPerChannel {};

使用它,您可以将您的泛型方法限制为某些属性组合。如果您的方法应该只处理 4 channel 和 32bpc 纹理:

void MyMethod<TChannels, TBPC>(Texture<TChannels, TBPC> foo)
where TChannels : FourChannels
where TBPC : BitsPerChannel_32


现在,每件好事也有阴暗面。你会如何做这样的事情(写成伪代码)?

switch (NumOfChannelsAttribute)
{
case FourChannels:
// do something
break;

case ThreeChannels:
// do something else
break;
}

你不能,至少不能以简单的方式,因为“FourChannel”和“ThreeChannel”是类型,而不是整数值。

当然,您仍然可以使用if 结构。为此,您需要在提供所用属性的通用纹理类型中实现一个属性:

class Texture<TChannels, TBPC> where TChannels : INumOfChannels,new() where TBPC : IBitsPerChannel,new()
{
public Type ChannelsAttribute
{
get { return typeof(TChannels); }
}

public Type BitsPerChannelAttribute
{
get { return typeof(TBPC); }
}
}

if 构造中,您可以按如下方式使用它:

var myTex = new Texture<FourChannels, BitsPerChannel_32>();

if (myTex.ChannelsAttribute == typeof(FourChannels))
{
... do something with 4 channels
}
else
{
... though luck, only 4 channels are supported...
}


最后的说明和建议:
虽然这可能会解决您的问题,但诉诸这些“技巧”通常表明设计存在缺陷。如果您重新审视您在代码中做出的设计选择,我认为这是值得投入的时间,因此您不需要像这样依赖拐杖。

关于C#类实例属性机制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19476496/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com