أفضل طريقة لتحويل VB6 "حدد الحالة 1067 إلى 2938 ..." إلى C#؟

StackOverflow https://stackoverflow.com/questions/3584395

سؤال

أقوم بتحويل بعض منطق VB6 إلى C# وواجهت عبارة SELECT/CASE التالية.

Select Case ZipCode
Case 1067 To 19417, 35075 To 35085, 48455 To 48465, 55583 To 55596, 67480 To 67551, 75392, 85126, _
    93047 To 93059, 21217 To 21739, 35091 To 35096, 48480, 55606 To 55779, 67655 To 67707, 76726 To 76835, _
    85221 To 87679, 94315 To 94419, 22844 To 25799, 35102, 48488, 56154 To 56254, 67731 To 67759, 76855 To 76889, _
    87719 To 88339, 94428 To 94437, 25868, 35112, 48499 To 48531, 56271, 67824 To 67829, 77761, 88353, 94522, _
    25879, 35117, 48653, 56281 To 56299, 69427 To 69429, 77773 To 77776, 88361 To 88364, 94553, 26121 To 26160, _
    35216 To 35282, 48720 To 48727, 56321 To 56337, 69437 To 69439, 78048 To 78126, 88368 To 88379, 94559, _
    26180 To 26215, 35287 To 35469, 49124 To 49356, 56410 To 56479, 70173 To 71287, 78136 To 79117, 88410, 95028 To 95032, _
    26316 To 26389, 35576 To 35768, 49406, 56575, 71332 To 71540, 80331 To 83313, 88481, 95111 To 95152, _
    26419, 36110, 49419, 56626 To 56648, 71546 To 71711, 83324 To 83362, 88529, 95176 To 95185, _
    26434 To 26441, 36304 To 36358, 49448, 56727 To 56745, 71720 To 72189, 83365 To 83379, 88633, 95188 To 95194, _
    26452, 36367 To 36369, 49453, 56751 To 57339, 72250 To 72417, 83413, 88662 To 90491, 95197

أفضل تحويل يمكنني التفكير فيه هو سلسلة من عبارات if/then/else التي تعرض لكل نطاق ، على سبيل المثال

if((ZipCode >= 1067 && ZipCode <=19417) ||
   (ZipCode >= 35075 && ZipCode <=35085) ||
   ...

أم أن هناك طريقة أفضل ، مثل بطريقة ما لوضع قيم النطاق هذه في تجزئة/مجموعة/مجموعة من نوع ما؟

هل كانت مفيدة؟

المحلول

على افتراض أنك تستخدم 3.5 أو أعلى, والوصول إلى طرق التمديد:

إذا كان لدي العديد من المقارنات ، فسأخلق طريقة لطيفة لنفسي:

public static class IntUtils
{
    public static bool InRange(this int value, int low, int high)
    {
        return value <= low && value <= high;
    }
}

ثم لاستخدامه:

if (zipCode.InRange(1067, 19417) ||
    zipCode.InRange(35075, 35085) || ...

إذا لم يكن لديك 3.5 أو لا تريد استخدام طرق التمديد:

public static class IntUtils
{
    public static bool InRange(int value, int low, int high)
    {
        return value <= low && value <= high;
    }
}

ثم لاستخدامه:

if (IntUtils.InRange(zipCode, 1067, 19417) ||
    IntUtils.InRange(zipCode, 35075, 35085) || ...

نصائح أخرى

ربما يمكنك إنشاء طريقة تمديد على int مثل:

private static bool Between (this int i, int lower, int upper)
{
  return i >= lower && i <= upper;
}

واستخدامه في رمز مثل

if ZipCode.Between(1067, 19417) || ZipCode.Between(35075, 35085) || ...

أفكار إضافية

إذا قمت بالمعالجة بناءً على هذا ، فربما يمكنك استخدام شيء على هذا المنوال

Dictionary<int[], Action> actionMap = new Dictionary<int[], Action>
{
  {new[]{1067,19417}, ProcessA},
  {new[]{35075, 35085}, ProcessB}
};

public void ProcessA()
{
  // do something;
}

public void ProcessB()
{
  // do something else;
}

public void Process(int zipCode)
{
  var action = actionMap.FirstOrDefault(a => zipCode >= a.Key[0] && zipCode <= a.Key[1]);
  if (action.Value != null)
  {
     action.Value();
  }
}

PS لست متأكدًا من أن هذا هو رمز العمل بنسبة 100 ٪ ، وكتبه من أعلى رأسي PPS Triead والآن أنا متأكد تمامًا من أنها تعمل

الطريقة التي تصفها هي التحول الحرفي من VB إلى C#. ومع ذلك ، فهذه بيانات كثيرة لدرجة أنها تبدو أفضل حالًا في ملف التكوين أكثر من الكود. إذا قمت بذلك ، فربما تكون أسهل طريقة هي ببساطة حلقة من خلال القائمة مع zipcodes ومقارنتها واحدة تلو الأخرى.

تتمثل الطريقة الأكثر فاعلية في فرز الرموز الرمودية والقيام بإجراء بحث ثنائي ، أو استخدام وظيفة التجزئة أو شيء من هذا القبيل ، لكنني سأفاجأ إذا تبين أنه عنق الزجاجة الأداء.

إذا كنت ترغب في جعل بعض الأساليب المعطاة أكثر تجريدًا ، فيمكنك الذهاب مع طريقة تمديد من هذا القبيل:

public static class Utils
{
    public static bool InRange<T>(this T value, T low, T high) where T : IComparable
    {
        return low.CompareTo(value) <= 0 && high.CompareTo(value) >= 0;
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top