質問の最後にある更新も参照してください...
次の状況を考えると:
[Flags]
enum SourceEnum
{
SNone = 0x00,
SA = 0x01,
SB = 0x02,
SC = 0x04,
SD = 0x08,
SAB = SA | SB,
SALL = -1,
}
[Flags]
enum DestEnum
{
DNone = 0x00,
DA = 0x01,
DB = 0x02,
DC = 0x04,
DALL = 0xFF,
}
big switch()のような名前を使用したマッピング関数に基づいて、ある列挙型を別の列挙型に、またはその逆に変換したいのですが、これはフラグ列挙型であるため、このようなルーチンを汎用として設計するのに苦労しています。
基本的に、私が欲しいのは次のようなものです。
例1
SourceEnum source = SourceEnum.SA;
DestEnum dest = Map<Source, Dest> (source);
Assert.That (dest, Is.EqualTo (DestEnum.DA));
例2
SourceEnum source = SourceEnum.SA | SourceEnum.SB;
DestEnum dest = Map<Source, Dest> (source);
Assert.That (dest, Is.EqualTo (DestEnum.DA | DestEnum.DB));
例3
SourceEnum source = SourceEnum.SAB;
DestEnum dest = Map<Source, Dest> (source);
Assert.That (dest, Is.EqualTo (DestEnum.DA | DestEnum.DB));
例4
SourceEnum source = SourceEnum.SALL;
DestEnum dest = Map<Source, Dest> (source);
Assert.That (dest, Is.EqualTo (DestEnum.DALL));
例5
SourceEnum source = SourceEnum.SD;
var ex = Assert.Throws<Exception> (() => Map<Source, Dest> (source));
Assert.That (ex.Message, Is.EqualTo ("Cannot map SourceEnum.SD to DestEnum!"));
Map()関数は、実際のマッピングを提供するためのデリゲートを受け入れることができますが、そのようなデリゲートをビットで支援するためのいくつかの関数が必要です...
DestEnum SourceToDestMapper (SourceEnum source)
{
// Switch cannot work with bit fields enumeration...
// This is to give the general idea...
switch (source)
{
case SourceEnum.SNone:
return DestEnum.DNone;
case SourceEnum.SA:
return DestEnum.DA;
case SourceEnum.SAB:
return DestEnum.DA | DestEnum.DB;
...
default:
throw new Exception ("Cannot map " + source.ToString() + " to DestEnum!");
}
}
編集:説明
列挙型定義の値は互いに適合しているように見えるかもしれませんが、必ずしもそうであるとは限りません。
たとえば、次のようになります。
enum SourceEnum
{
SA = 0x08,
SB = 0x20,
SC = 0x10,
SAB = SA | SB,
SABC = SA | SB | SC,
}
enum DestEnum
{
DA = 0x04,
DB = 0x80,
DC = 0x01,
DAB = DA | DB,
}
編集:詳細
名前のパターンに基づくのではなく、列挙型フラグのカスタムマッピングを行う方法を検討しています。ただし、名前はカスタムマッピング関数で使用されます。
たとえば、SAをDCにマップしようとするSourceToDestMapper関数を使用することは完全に可能です...
主な問題は、SourceToDestMapper関数にソースの各フラグをフィードし、複数のビットセットを持つフラグ値を処理することです。
例:フラグSourceEnum.SABCがあると、SourceToDestMapper関数が3回呼び出され、次のようになります。
- DestEnum.DAにマップされたSourceEnum.SA
- DestEnum.DBにマップされたSourceEnum.SB
- DestEnum.DCにマップされたSourceEnum.SC
そして、結果のDestEnumは次のようになります。DestEnum.DB | DestEnum.DC