parsley72
parsley72

Reputation: 9087

How to elegantly search an array of struct in C#, porting from C++?

I have some C++ code I'm rewriting in C#. I'm strong in C++ but new to C# so, although my C# code works fine I can't help thinking there's a more elegant way of doing this.

This is the converted C# code - the original C++ code is below:

public partial class NativeConstants
{
    public const uint ID_50PS = 0;  // 50 per second (20ms)
    public const uint ID_20PS = 1;  // 20 per second (50ms)
    public const uint ID_10PS = 2;  // 10 per second (100ms)
    public const uint ID_5PS = 3;  // 5 per second (200ms)
    public const uint ID_2PS = 4;  // 2 per second (500ms)
    public const uint ID_1S = 5;
    public const uint ID_2S = 6;
    public const uint ID_5S = 7;
    public const uint ID_10S = 8;
    public const uint ID_15S = 9;
    public const uint ID_20S = 10;
    public const uint ID_30S = 11;
    public const uint ID_1MIN = 12;
    public const uint ID_2MIN = 13;
    public const uint ID_5MIN = 14;
    public const uint ID_10MIN = 15;
    public const uint ID_15MIN = 16;
    public const uint ID_20MIN = 17;
    public const uint ID_30MIN = 18;
    public const uint ID_1HR = 19;
    public const uint ID_24HR = 20;
    public const uint ID_400PS = 21; // 400 per second (2.5ms)
    public const uint ID_200PS = 22; // 200 per second (5ms)
    public const uint ID_100PS = 23; // 100 per second (10ms)
}

struct SPeriodInfo
{
    public string   strItem;
    public int      nItemData;
    public float    fPeriod;

    public SPeriodInfo(string item, int itemData, float period)
    {
        strItem = item;
        nItemData = itemData;
        fPeriod = period;
    }
}
static readonly SPeriodInfo[] PeriodInfo = new SPeriodInfo[]
{
    new SPeriodInfo("20 ms",  NativeConstants.ID_50PS, (float)0.020),
    new SPeriodInfo("50 ms",  NativeConstants.ID_20PS, (float)0.050),
    new SPeriodInfo("100 ms", NativeConstants.ID_10PS, (float)0.100),
    new SPeriodInfo("200 ms", NativeConstants.ID_5PS, (float)0.200),
    new SPeriodInfo("500 ms", NativeConstants.ID_2PS, (float)0.500),
    new SPeriodInfo("1 sec",  NativeConstants.ID_1S, (float)1.0),
    new SPeriodInfo("2 sec",  NativeConstants.ID_2S, (float)2.0),
    new SPeriodInfo("5 sec",  NativeConstants.ID_5S, (float)5.0),
    new SPeriodInfo("10 sec", NativeConstants.ID_10S, (float)10.0),
    new SPeriodInfo("15 sec", NativeConstants.ID_15S, (float)15.0),
    new SPeriodInfo("20 sec", NativeConstants.ID_20S, (float)20.0),
    new SPeriodInfo("30 sec", NativeConstants.ID_30S, (float)30.0),
    new SPeriodInfo("1 min",  NativeConstants.ID_1MIN, (float)60.0),
};

float fPeriod = 0;
for (int i = 0; i < PeriodInfo.Count(); ++i)
{
    if (PeriodInfo[i].nItemData == slmRecordData.m_Settings.m_nSamplePeriod)
    {
        fPeriod = PeriodInfo[i].fPeriod;
        break;
    }
}

This is the original C++ code:

#define ID_50PS                        0  // 50 per second (20ms)
#define ID_20PS                        1  // 20 per second (50ms)
#define ID_10PS                        2  // 10 per second (100ms)
#define ID_5PS                         3  // 5 per second (200ms)
#define ID_2PS                         4  // 2 per second (500ms)
#define ID_1S                          5
#define ID_2S                          6
#define ID_5S                          7
#define ID_10S                         8
#define ID_15S                         9
#define ID_20S                         10
#define ID_30S                         11
#define ID_1MIN                        12
#define ID_2MIN                        13
#define ID_5MIN                        14
#define ID_10MIN                       15
#define ID_15MIN                       16
#define ID_20MIN                       17
#define ID_30MIN                       18
#define ID_1HR                         19
#define ID_24HR                        20
#define ID_400PS                       21 // 400 per second (2.5ms)
#define ID_200PS                       22 // 200 per second (5ms)
#define ID_100PS                       23 // 100 per second (10ms)

typedef struct
{
    std::wstring    wstrItem;
    int             nItemData;
    float           fPeriod;
} SPeriodInfo;

SPeriodInfo PeriodInfo [] =
{
    {L"20 ms",  ID_50PS, (float)0.020},
    {L"50 ms",  ID_20PS, (float)0.050},
    {L"100 ms", ID_10PS, (float)0.100},
    {L"200 ms", ID_5PS, (float)0.200},
    {L"500 ms", ID_2PS, (float)0.500},
    {L"1 sec",  ID_1S, (float)1.0},
    {L"2 sec",  ID_2S, (float)2.0},
    {L"5 sec",  ID_5S, (float)5.0},
    {L"10 sec", ID_10S, (float)10.0},
    {L"15 sec", ID_15S, (float)15.0},
    {L"20 sec", ID_20S, (float)20.0},
    {L"30 sec", ID_30S, (float)30.0},
    {L"1 min",  ID_1MIN, (float)60.0},
};

float fPeriod = 0;
for (int i = 0; i < _countof(PeriodInfo); ++i)
{
    if (PeriodInfo[i].nItemData == slmRecordData.m_Settings.m_nSamplePeriod)
    {
        fPeriod = PeriodInfo[i].fPeriod;
        break;
    }
}

Upvotes: 0

Views: 145

Answers (2)

quantdev
quantdev

Reputation: 23803

1) Use auto properties, and use a class for SPeriodInfo (class and struct have very different semantics in C#)

class SPeriodInfo
{
    public string   strItem   { get; private set; }
    public int      nItemData { get; private set; }
    public float    fPeriod   { get; private set; }

    public SPeriodInfo(string item, int itemData, float period)
    {
        strItem = item;
        nItemData = itemData;
        fPeriod = period;
    }
}

2) Don't use a hand-written loop to search for the period, you can use Array.Find or Linq :

float fPeriod = Array.Find(PeriodInfo,
    element => element.nItemData == slmRecordData.m_Settings.m_nSamplePeriod);

Or

float fPeriod = PeriodInfo.FirstOrDefault(p=>p.nItemData == slmRecordData.m_Settings.m_nSamplePeriod).fPeri‌​od;

Upvotes: 1

Jim Mischel
Jim Mischel

Reputation: 134025

The simple LINQ expression is:

float fPeriod = PeriodInfo.FirstOrDefault(p => p.nItemData == slmRecordData.m.Settings.m_nSamplePeriod).fPeriod;

Upvotes: 0

Related Questions