কোনও বস্তু সি # তে একটি সংখ্যা কিনা তা পরীক্ষা করা হচ্ছে


91

আমি একটি বস্তু একটি সংখ্যা যাতে চেক করতে চাই .ToString()একটি স্ট্রিং সংখ্যা ধারণকারী এবং স্থাপিত হবে +, -,.

নেট টাইপ করে। নেট (যেমন if (p is Number):) পরীক্ষা করে কি সম্ভব ?

বা আমার কি স্ট্রিংয়ে রূপান্তর করা উচিত, তারপরে দ্বিগুণ করার চেষ্টা করুন?

আপডেট: আমার অবজেক্টটি পরিষ্কার করার জন্য হ'ল ইনট, ইউিন্ট, ফ্লোট, ডাবল এবং আরও কিছু এটি স্ট্রিং নয়। আমি এমন একটি ফাংশন তৈরির চেষ্টা করছি যা এই জাতীয় xML তে কোনও বস্তুকে সিরিয়ালাইজ করবে:

<string>content</string>

বা

<numeric>123.3</numeric>

বা একটি ব্যতিক্রম বাড়াতে।


4
আপনি মত শোনাচ্ছে আপনার নিজের XmlSerializer- কি .NET- পর এক প্রদানকারীর সাথে ভুল লিখতে চেষ্টা করছেন msdn.microsoft.com/en-us/library/... ?
রিচার্ডড

4
আপনি কোনও এক্সএসডি ব্যবহার করে আপনার এক্সএমএল ফর্ম্যাটটি সংজ্ঞায়িত করে এবং তারপরে এমন কোনও বস্তু তৈরি করতে পারবেন যাতে আপনি প্রেরিত এক্সএসডি
ডেক্সটার

@ রিচার্ডড: আমি কি বস্তু সিরিয়াল করতে এক্সএমএল সিরিয়ালাইজেশন ব্যবহার করতে পারি []? আমার এটি ফ্ল্যাশ ফাংশনটি অ্যাডোব.লাইভডকসস
পাইওটার সিজাপলা

উত্তর:


183

প্রতিটি মৌলিক সংখ্যার জন্য আপনাকে কেবল টাইপ চেক করতে হবে।

কাজটি করা উচিত এমন একটি এক্সটেনশন পদ্ধতি এখানে:

public static bool IsNumber(this object value)
{
    return value is sbyte
            || value is byte
            || value is short
            || value is ushort
            || value is int
            || value is uint
            || value is long
            || value is ulong
            || value is float
            || value is double
            || value is decimal;
}

এটিতে সমস্ত সংখ্যার প্রকার coverেকে রাখা উচিত।

হালনাগাদ

দেখে মনে হচ্ছে আপনি ডিসাইরিয়ালাইজেশন চলাকালীন সময়ে একটি স্ট্রিং থেকে সংখ্যাটি সংশ্লেষ করতে চান। এই ক্ষেত্রে, সম্ভবত এটি ব্যবহার করা ভাল double.TryParse

string value = "123.3";
double num;
if (!double.TryParse(value, out num))
    throw new InvalidOperationException("Value is not a number.");

অবশ্যই, এটি খুব বড় পূর্ণসংখ্যার / দীর্ঘ দশমিকগুলি পরিচালনা করবে না, তবে যদি এটি হয় তবে আপনাকে কেবল long.TryParse/ decimal.TryParse/ অন্য যে কোনও কিছুতে অতিরিক্ত কল যুক্ত করতে হবে।


আমার অবজেক্টটি হ'ল ইনট, শর্ট, ইউিন্ট, ফ্লোট, ডাবল বা অন্য কোনও কিছু যা একটি সংখ্যা
পাইট্রার জাজাপলা

@ পাইওটার: ঠিক আছে। মনে হচ্ছে আমি আপনাকে ভুল বুঝেছি। আমার আপডেট হওয়া উত্তরটি দেখুন।
নলডোরিন

4
@ নলডোরিন: আসলে কোডটির আগের সংস্করণটিও কাজ করবে; কেবল একটি নাল চেক যুক্ত করুন এবং মানটি ব্যবহার করুন oস্ট্রাস্টিং ()। তারপরে আপনাকে সমস্ত সংখ্যার প্রকারের জন্য পরীক্ষা করার দরকার নেই।
ফ্রেডরিক মের্ক

4
@ নলডোরিন দুঃখের বিষয় যে এটির সঠিক সমাধানটি হ'ল ক্রিয়াপদ :(।
পাইটর জাজাপলা

4
@ জো: আসলে, এতে কোনও পার্থক্য হবে না, যেহেতু টস্ট্রিংও বর্তমান সংস্কৃতি ব্যবহার করবে।
নলডোরিন

36

স্কট হ্যানসেলম্যানের ব্লগ থেকে নেওয়া :

public static bool IsNumeric(object expression)
{
    if (expression == null)
    return false;

    double number;
    return Double.TryParse( Convert.ToString( expression
                                            , CultureInfo.InvariantCulture)
                          , System.Globalization.NumberStyles.Any
                          , NumberFormatInfo.InvariantInfo
                          , out number);
}

6
এই পদ্ধতির সমস্যাটি হ'ল যদি আপনি কোনও স্ট্রিংয়ে পাস করেন যা দেখতে একটি সংখ্যার মতো লাগে তবে এটি বিন্যাস করবে। বেশিরভাগ লোকের পক্ষে ঠিক থাকতে পারে তবে এটি আমার জন্য শো স্টপার ছিল।
রব সেডগুইক

4
এর সাথে আর একটি সম্ভাব্য সমস্যা হ'ল আপনি নূন্যতম / সর্বোচ্চ মানগুলি দ্বিগুণ করতে পারছেন না। double.Parse(double.MaxValue.ToString())কারণ একটি OverflowException। আপনি এক্ষেত্রে রাউন্ডট্রিপ সংশোধক সরবরাহ করে এর প্রতিকার করতে পারেন .ToString("R"), তবে সেই ধরণের ওভারলোড উপলব্ধ নেই Convert.ToString(...)কারণ আমরা প্রকারটি জানি না। আমি জানি এটি কিছুটা ফ্রঞ্জের কেস তবে আমার নিজের .IsNumeric()এক্সটেনশনের পরীক্ষার লেখার সময় আমি এতে হোঁচট খেয়েছি । আমার "সমাধান" হ'ল কোনও কিছু পার্স করার চেষ্টা করার আগে টাইপ চেকিং সুইচ যুক্ত করা ছিল, কোডটির জন্য এই প্রশ্নের আমার উত্তরটি দেখুন।
বেন

21

একটি সহজ এক্সটেনশন পদ্ধতি করতে ইসপ্রাইমটিভ সম্পত্তি ব্যবহার করুন:

public static bool IsNumber(this object obj)
{
    if (Equals(obj, null))
    {
        return false;
    }

    Type objType = obj.GetType();
    objType = Nullable.GetUnderlyingType(objType) ?? objType;

    if (objType.IsPrimitive)
    {
        return objType != typeof(bool) && 
            objType != typeof(char) && 
            objType != typeof(IntPtr) && 
            objType != typeof(UIntPtr);
    }

    return objType == typeof(decimal);
}

সম্পাদনা: মন্তব্য অনুযায়ী স্থির। জেনেরিকগুলি মুছে ফেলা হয়েছে .GetType () বাক্স মান ধরণের। অযোগ্য মানগুলির জন্য সংশোধনও অন্তর্ভুক্ত।


4
জেনেরিক অংশটি আপনাকে এখানে কোনও বাড়তি দিচ্ছে না, তাই না? আপনি কেবলমাত্র গেটটাইপ () অ্যাক্সেস করতে পারেন যা অবজেক্টে উপলভ্য ...
পিটার লিলিভল্ড

যদি কোনও মানের ধরণে কল করা হয় তবে এটি একটি বাক্স অপারেশন সংরক্ষণ করে। পুনরায় ব্যবহারযোগ্যতা চিন্তা করুন।
কেনান ই কে

4
অবজেক্টের পরিবর্তে টাইপফ (টি) কেন ব্যবহার করবেন না et গেটটাইপের মাধ্যমে, কেউ যদি নাল রেফারেন্স টাইপ পাস করে তবে আপনি নুলারফেরান এক্সেক্সপশন পাবেন না। আপনি কেবলমাত্র মান ধরণের গ্রহণ করতে টি তে একটি জেনেরিক বাধাও রাখতে পারেন। আপনি যদি এটি করেন তবে অবশ্যই সংকলনের সময় আপনার প্রচুর তথ্য থাকা শুরু।
ট্রিলিয়ান

objectএবং stringএটি আদিম ধরণের নয়।
আমরা সমস্ত মনিকা

@ জেনিলেন: এই উত্তরটি বেশ কিছুক্ষণ আগে ছিল। আমি বিশ্বাস করি আমি সেই সময়ে প্রতিফলিত কাঠামোর উত্স থেকে কিছুটা খনন করেছি, তবে আজ কে বলতে পারে ... স্থির উত্তর।
কেনান ই কে

10

উপরে কিছু দুর্দান্ত উত্তর আছে। এখানে একটি সর্বাত্মক সমাধান রয়েছে। বিভিন্ন পরিস্থিতিতে তিনটি ওভারলোড।

// Extension method, call for any object, eg "if (x.IsNumeric())..."
public static bool IsNumeric(this object x) { return (x==null ? false : IsNumeric(x.GetType())); }

// Method where you know the type of the object
public static bool IsNumeric(Type type) { return IsNumeric(type, Type.GetTypeCode(type)); }

// Method where you know the type and the type code of the object
public static bool IsNumeric(Type type, TypeCode typeCode) { return (typeCode == TypeCode.Decimal || (type.IsPrimitive && typeCode != TypeCode.Object && typeCode != TypeCode.Boolean && typeCode != TypeCode.Char)); }

নাল চেক যোগ করার কথা বিবেচনা করুন
wiero

সত্যিই নাল চেকের দরকার নেই - একটি এক্সটেনশন পদ্ধতি হিসাবে আপনি এটিকে নাল মান দিয়ে কল করতে পারেন না। অবশ্যই কেউ এখনও সাধারণ ফাংশন হিসাবে কল করতে পারে তবে এটি কোনও এক্সটেনশন পদ্ধতির প্রত্যাশিত ব্যবহার নয়।
মিক ব্রুনো

4
আমি মনে করি যে কেউ একে নাল মান দিয়ে কল করতে পারে। অবজেক্ট আপত্তি = নাল; obj.IsNumeric ();
উইয়েরো

ধন্যবাদ ওয়েয়ারো, এটি ঠিক করে দিয়েছেন। নাল মান সহ কলিং এক্সটেনশন পদ্ধতিটি উপলব্ধি করা সম্ভব হয়নি তবে অবশ্যই এটি!
মিক ব্রুনো

আমার মনে হয় প্রথম ওভারলোডের শেষে একটি প্রথম বন্ধনী অনুপস্থিত: "রিটার্ন (x == নাল? মিথ্যা: ইসনুমারিক (এক্স। গেটটাইপ ()));"
গ্লেন গারসন

8

নিজের ঘূর্ণায়মানের পরিবর্তে, অন্তর্নির্মিত প্রকারটি সংখ্যাসূচক কিনা তা বলার সবচেয়ে নির্ভরযোগ্য উপায় সম্ভবত রেফারেন্স Microsoft.VisualBasicএবং কল করা Information.IsNumeric(object value)। বাস্তবায়নটি char[]এইচএক্স এবং ওসিটি স্ট্রিংয়ের মতো কয়েকটি সূক্ষ্ম কেস পরিচালনা করে।


এটি শীর্ষে থাকা উচিত!
নওফাল

4

তিনটি পৃথক ধারণা আছে:

  • যদি এটা চেক করতে হয় একটি সংখ্যা (অর্থাত একটি (সাধারণত boxed) সাংখ্যিক মান নিজেই), টাইপ পরীক্ষা is- উদাহরণস্বরূপif(obj is int) {...}
  • একটি সংখ্যা হিসাবে একটি স্ট্রিং পার্স করা যায় কিনা তা পরীক্ষা করতে; ব্যবহারTryParse()
  • তবে যদি বস্তুটি কোনও সংখ্যা বা স্ট্রিং নয় তবে আপনি সন্দেহ করছেন ToString()যে কোনও সংখ্যার মতো দেখতে কিছু দেয় তবে তারপরে কল করে ToString() স্ট্রিং হিসাবে আচরণ করুন

উভয় প্রথম দুই ক্ষেত্রে, আপনি সম্ভবত আলাদাভাবে প্রতিটি সাংখ্যিক প্রকার সমর্থন করতে চান পরিচালনা করতে হবে ( double/ decimal/ int) - প্রতিটি ভিন্ন রেঞ্জ এবং নির্ভুলতার, উদাহরণস্বরূপ আছে।

আপনি দ্রুত রুক্ষ চেকের জন্য রেজেক্সেও নজর রাখতে পারেন।


4

আপনার ইনপুটটি স্ট্রিং হিসাবে ধরে নেওয়া হচ্ছে ...

এখানে 2 টি উপায় রয়েছে:

Double.TryParse () ব্যবহার করুন

double temp;
bool isNumber = Double.TryParse(input, out temp);

Regex ব্যবহার করুন

 bool isNumber = Regex.IsMatch(input,@"-?\d+(\.\d+)?");

4

আপনি এই জাতীয় কোড ব্যবহার করতে পারেন:

if (n is IConvertible)
  return ((IConvertible) n).ToDouble(CultureInfo.CurrentCulture);
else
  // Cannot be converted.

আপনার বস্তু একটি হয়, তাহলে Int32, Single, Doubleইত্যাদিতে রূপান্তর কার্য সম্পাদনা করবে। এছাড়াও, একটি স্ট্রিং প্রয়োগ করে IConvertibleতবে স্ট্রিংটি যদি ডাবলকে রূপান্তরিত না করে তবে একটি FormatExceptionনিক্ষেপ করা হবে।


প্রকৃতপক্ষে স্ট্রিংগুলি বিশ্লেষণ করা হবে, তবে সঠিক বিন্যাসে না থাকলে ফর্ম্যাটএক্সসেপশন নিক্ষেপ করা হবে।
alfoks

@ অ্যালফক্স: আপনি একেবারে ঠিক বলেছেন তাই আমি উত্তর আপডেট করেছি।
মার্টিন লিভারেজ

1

আপনার প্রয়োজন যদি সত্যিই হয়

.ToString () এর ফলে অঙ্কগুলি এবং +, - যুক্ত স্ট্রিং তৈরি করতে পারে would

এবং আপনি ডাবলটি ব্যবহার করতে চান ry ট্রাইপার্স করে তারপরে আপনাকে একটি ওভারলোডটি ব্যবহার করতে হবে যা একটি নম্বরস্টাইলস প্যারামিটার লাগে এবং নিশ্চিত করে নিন যে আপনি আক্রমণকারী সংস্কৃতিটি ব্যবহার করছেন।

উদাহরণস্বরূপ এমন একটি সংখ্যার জন্য যার একটি শীর্ষস্থানীয় চিহ্ন থাকতে পারে, কোনও নেতৃস্থানীয় বা চলমান শ্বেত স্পেস নেই, হাজার হাজার বিভাজক এবং একটি সময়কালের দশমিক বিভাজক ব্যবহার করুন:

NumberStyles style = 
   NumberStyles.AllowLeadingSign | 
   NumberStyles.AllowDecimalPoint | 
double.TryParse(input, style, CultureInfo.InvariantCulture, out result);

1

আমার নিজের লেখার সময় object.IsNumeric()আপনি একটি পাবেন এক্সটেনশন পদ্ধতি এই প্রশ্ন আমি যে একটি সম্ভাব্য ইস্যু গাড়ীতে আঘাত শৌলের Dolgin এর উত্তর ভিত্তিক OverflowExceptionযদি আপনি এটি দিয়ে চেষ্টা double.MaxValueকরুন অথবা double.MinValue

আমার "সমাধান" হ'ল নলডোরিনের গৃহীত উত্তরটি শৌল ডলগিনের সাথে উত্তরটির সাথে একত্রিত করা এবং কোনও কিছু পার্স করার চেষ্টা করার আগে একটি প্যাটার্ন ম্যাচিং সুইচ যুক্ত করুন (এবং কিছুটা পরিষ্কার করার জন্য কিছু সি # 7 ধার্মিকতা ব্যবহার করুন):

public static bool IsNumeric(this object obj)
{
    if (obj == null) return false;

    switch (obj)
    {
        case sbyte _: return true;
        case byte _: return true;
        case short _: return true;
        case ushort _: return true;
        case int _: return true;
        case uint _: return true;
        case long _: return true;
        case ulong _: return true;
        case float _: return true;
        case double _: return true;
        case decimal _: return true;
    }

    string s = Convert.ToString(obj, CultureInfo.InvariantCulture);

    return double.TryParse(s, NumberStyles.Any, NumberFormatInfo.InvariantInfo, out double _);
}

নালার ধরণের বিষয়ে সাবধান থাকুন।
গিলারমো প্রান্ডি

0

হ্যাঁ, এটি কাজ করে:

object x = 1;
Assert.That(x is int);

ভাসমান পয়েন্ট নম্বরের জন্য আপনাকে ভাসমানের ধরণটি ব্যবহার করে পরীক্ষা করতে হবে:

object x = 1f;
Assert.That(x is float);

এটি কাজ করবে যদি কোনও বস্তুকে স্পষ্টভাবে বা স্পষ্টতই কাস্ট করার আগে অবজেক্টটি কোন int ছিল। আপনার উদাহরণস্বরূপ, ম্যাজিক নম্বর 1টি একটি অন্তর্নিহিত, এবং এরপরে ভেরিয়েবল x এর ধরণের ক্ষেত্রে জড়িত .. .. যদি আপনি x = 1.0 অবজেক্টটি করেন তবে আপনার দাবীটি মিথ্যা ফিরে আসত।
ডেক্সটার

এমন সংখ্যা রয়েছে যা অন্তর্নিহিত নয়।
ফ্রেডরিক মের্ক

হ্যাঁ, তাই আমার বক্তব্যটি এখনই নলডোরিনের উত্তরে যা আছে।
পিটার লিলিভল্ড
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.