วิธีการทั่วไปในการตรวจสอบ int, double GetType() ใช้งานอย่างไร?

ฉันกำลังพยายามเขียนวิธีการตรวจสอบ เช่น สำหรับ double ดูเหมือนว่านี้:

   protected bool ValidateLoopAttributes(string i_value, double i_threshold)
       {
        double result;
        if (!(double.TryParse(i_value, out result) && result >= i_threshold))
        {
            return false;
        }
        return true;
    }

เป็นไปได้ไหมที่จะเขียนสิ่งนี้เป็น:

     protected bool ValidateLoopAttributes<T>(string i_value, T i_threshold)

แล้วใช้บางอย่างเช่น

             T.GetType().TryParse() // how can i use here the type's methods??

การใช้คำสั่ง switch/if เป็นวิธีเดียวที่จะทำสิ่งนี้หรือไม่? เช่น:

    If (T.GetType() is int) 
        Int32.TryParse(i_threshold)

มีวิธีที่สง่างามกว่านี้ไหม?


person Dan Dinu    schedule 13.04.2012    source แหล่งที่มา
comment
ตรวจสอบคำตอบของ Marc Gravell ในโพสต์นี้: stackoverflow.com/questions/1654871/   -  person Marco    schedule 13.04.2012
comment
GetType() เป็นวิธีการแบบอินสแตนซ์ ดังนั้น T.GetType() จึงไม่ควรคอมไพล์ด้วยซ้ำ คุณต้องใช้ typeof(T)   -  person Cristian Lupascu    schedule 13.04.2012
comment
ทำไมต้องไปเจอปัญหาทั้งหมดนี้? หากคุณกังวลแค่เรื่องการลอยตัวและจำนวนเต็ม ทำไมไม่โอเวอร์โหลดสองครั้ง ValidateLoopAttributes(string i_value, double i_threshold) และ ValidateLoopAttributes(string i_value, int i_threshold) (หรือ long)   -  person Rawling    schedule 13.04.2012


คำตอบ (4)


ลองสิ่งนี้:

static class Ext
{
    public static bool TryParse<T>(string s, out T value)
    {
        TypeConverter converter = TypeDescriptor.GetConverter(typeof(T));
        try
        {
            value = (T)converter.ConvertFromString(s);
            return true;
        }
        catch
        {
            value = default(T);
            return false;
        }
    }
    public static bool ValidateLoopAttributes<T>(string i_value, T i_threshold) 
           where T : IComparable
    {
        T outval;
        if (TryParse<T>(i_value, out outval))
            return outval.CompareTo(i_threshold) >= 0;
        else return false;
    }
}

คำตอบของฉันใช้คำตอบของ Marc Gravell ที่นำมาจากที่นี่
ด้วยสิ่งนี้ คุณสามารถทำได้

bool b1 = Ext.ValidateLoopAttributes<int>("5", 4);
bool b2 = Ext.ValidateLoopAttributes<double>("5.4", 5.5d);

หากคุณพบว่ามีประโยชน์คุณสามารถใช้วิธีการขยายได้เช่นกัน

public static bool ValidateLoopAttributes<T>(this string i_value, T i_threshold) 
       where T : IComparable { }

ที่นำคุณไปสู่การใช้งาน

bool b1 = "5".ValidateLoopAttributes<int>(4);
bool b2 = "5.4".ValidateLoopAttributes<double>(5.5d);
person Marco    schedule 13.04.2012

ขณะนี้คุณกำลังผสมสองสิ่งในวิธีการของคุณ - การแยกวิเคราะห์และกฎเกณฑ์ทางธุรกิจ พิจารณาว่าคุณเรียกใช้ ValidateLoopAttributes(value, 4) และมันจะส่งคืน false เหตุผลที่เป็นไปได้:

  1. สตริงไม่มีค่า เช่น. ว่างเปล่า ตัวอักษรบางตัว ฯลฯ
  2. สตริงไม่มีค่าจำนวนเต็ม เช่น. มันมีค่าสองเท่า
  3. สตริงมีค่าจำนวนเต็ม แต่เกินขีดจำกัด
  4. ไม่มีตัวแปลงที่กำหนดไว้สำหรับประเภทของคุณ

ในกรณีแรก คุณมีข้อมูลที่ไม่ถูกต้องในแหล่งที่มาของคุณ ในกรณีที่สอง คุณมีรหัสที่ไม่ถูกต้อง ซึ่งควรใช้ double แทน ในกรณีที่รหัสกรณีที่สามก็โอเค แต่กฎเกณฑ์ทางธุรกิจถูกทำลาย ในกรณีสุดท้าย (ซึ่งไม่ใช่กรณีของเลขคู่หรือจำนวนเต็ม แต่ถ้าคุณเขียนโค้ดทั่วไปโดยไม่มีข้อจำกัดเกี่ยวกับประเภท คุณอนุญาตให้ผู้อื่นเรียกมันด้วยประเภทใดก็ได้) ปัญหาในโค้ดก็เช่นกัน

ดังนั้น ให้คิดถึงการแยกกฎเกณฑ์ทางธุรกิจและการแยกวิเคราะห์ข้อมูล

Foo foo = Parse(xml);
RunBusinessRules(foo); 
person Sergey Berezovskiy    schedule 13.04.2012

public static bool ValidateLoopAttributes<T>(string value, T threshold)
    where T : IComparable
{
    try
    {
        var parseMethod = typeof(T).GetMethod("Parse", new[] {typeof (string)});
        var result = (T) parseMethod.Invoke(null, new object[] {value});
        return result.CompareTo(threshold) < 0;
    }
    catch (Exception)
    {
        return false;
    }
}

แน่นอนว่าวิธีนี้ใช้ได้กับประเภทที่มีวิธีแยกวิเคราะห์แบบคงที่เท่านั้น

person Scroog1    schedule 13.04.2012

สามารถลองใช้สิ่งนี้เพื่อตรวจสอบว่านี่เป็นจำนวนเต็มหรือไม่:

public static bool IsNumericValue(string val, System.Globalization.NumberStyles NumberStyle)
{
    double result;
    return Double.TryParse(val,NumberStyle,
        System.Globalization.CultureInfo.CurrentCulture,out result);
}

so on

 IsNumericValue("1.2", System.Globalization.NumberStyles.Integer) // FALSE 

และต่อไป

 IsNumericValue("12", System.Globalization.NumberStyles.Integer)  // TRUE

โปรดทราบว่าในตัวอย่างนี้ นี้ ฉันใช้ CurrectCulture ปรับให้เหมาะกับความต้องการ ของคุณ หากมีความแตกต่างกัน

person Tigran    schedule 13.04.2012