সি # - কোনও প্রকারটি সংখ্যা কিনা তা নির্ধারণ করবেন


105

প্রদত্ত কি না তা নির্ধারণ করার কোনও উপায় আছে? নেট টাইপটি একটি সংখ্যা? উদাহরণস্বরূপ: System.UInt32/UInt16/Doubleসমস্ত সংখ্যা। আমি এর উপর একটি দীর্ঘ সুইচ-কেস এড়াতে চাই Type.FullName।


4
অনেকের, অনেকের, অনেকের upe কেন এটি এখনও বন্ধ করা হয়নি?
— নলডোরিন


উত্তর:


110

এটা চেষ্টা কর:

Type type = object.GetType();
bool isNumber = (type.IsPrimitiveImple && type != typeof(bool) && type != typeof(char));

আদিম প্রকারগুলি হ'ল বুলিয়ান, বাইট, এসবাইট, ইন্ট 16, ইউআইএনট 16, ইন্ট 32, ইউআইএনটি 32, ইন্ট 64, ইউআইএন 64, চর, ডাবল এবং একক।

টেকিং Guillaume, এর সমাধান একটু আরো:

public static bool IsNumericType(this object o)
{   
  switch (Type.GetTypeCode(o.GetType()))
  {
    case TypeCode.Byte:
    case TypeCode.SByte:
    case TypeCode.UInt16:
    case TypeCode.UInt32:
    case TypeCode.UInt64:
    case TypeCode.Int16:
    case TypeCode.Int32:
    case TypeCode.Int64:
    case TypeCode.Decimal:
    case TypeCode.Double:
    case TypeCode.Single:
      return true;
    default:
      return false;
  }
}

ব্যবহার:

int i = 32;
i.IsNumericType(); // True

string s = "Hello World";
s.IsNumericType(); // False

2
সুতরাং decimalটাইপ সংখ্যাটি নয়?
— লুক এইচ

2
@ কায়রো: আমার সন্দেহ নেই যে decimal এটি সংখ্যাসূচক। এটি আদিম নয় বলে এর অর্থ এটি সংখ্যাসূচক নয়। আপনার কোডটির জন্য এটি অ্যাকাউন্ট করা দরকার।
— লুক এইচ

2
এটি .NET 4.0 এ নতুন সংখ্যার জন্য নতুন ইঞ্জিনিয়ার করা দরকার যার টাইপ কোড নেই।
— জন স্কিটি

7
বর্তমান প্রযুক্তির উপর ভিত্তি করে আপনি কীভাবে আমাকে উত্তম করতে পারেন। হতে পারে। নেট 62 এ, INT মুছে ফেলা হবে - আপনি কি সমস্ত উত্তরকে অন্তর্নিহিত করতে যাচ্ছেন?
— ফিলিপ ওয়ালেস

1
@ ডিস্কজঙ্কি দুঃখিত, বন্ধু এটি প্রায় তিন বছর আগে ছিল এবং তাদের সামগ্রী কী ছিল তা আমার মনে নেই।
— kdbanman

93

একটি স্যুইচ ব্যবহার করবেন না - কেবল একটি সেট ব্যবহার করুন:

HashSet<Type> NumericTypes = new HashSet<Type>
{
    typeof(decimal), typeof(byte), typeof(sbyte),
    typeof(short), typeof(ushort), ...
};

সম্পাদনা: প্রকারের কোড ব্যবহারের মাধ্যমে এর একটি সুবিধা হ'ল যখন নতুন সংখ্যার প্রকারগুলি .NET (যেমন বিগআইন্টিজার এবং কমপ্লেক্স ) এর মধ্যে প্রবর্তিত হয় তখন এটি সামঞ্জস্য করা সহজ - যেখানে এই ধরণের কোনও টাইপ কোড পাবেন না ।


4
এবং আপনি কিভাবে হ্যাশসেট ব্যবহার করবেন?
— আরভিডিকে

8
NumericTypes.Contains (যাই হোক না কেন)?
— এমকিপিপি

3
বুল ইসানম্বার = সংখ্যার টাইপ.সামগ্রী (ক্লাসইনস্ট্যান্স.গেটটাইপ ());
— ইউরি ফক্টোরিভিচ

ভাবতেন যে সংকলকটি হ্যাশসেটে স্যুইচ-স্টেটমেন্টের অন্তর্নিহিত রূপান্তর করবে।
— রল্ফ ক্রিস্টেনসেন

6
@ রলফক্রিস্টেনসেন: ঠিক switchতেমন কাজ হয় না Type, তাই আপনি পারবেন না। আপনি TypeCodeঅবশ্যই চালু করতে পারেন , তবে এটি ভিন্ন বিষয় a
— জন স্কিটি

69

সমাধানগুলির কোনওটিই নুলকে বিবেচনায় নেয় না।

আমি জন স্কিটির সমাধানটি কিছুটা সংশোধন করেছি:

    private static HashSet<Type> NumericTypes = new HashSet<Type>
    {
        typeof(int),
        typeof(uint),
        typeof(double),
        typeof(decimal),
        ...
    };

    internal static bool IsNumericType(Type type)
    {
        return NumericTypes.Contains(type) ||
               NumericTypes.Contains(Nullable.GetUnderlyingType(type));
    }

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

    private static HashSet<Type> NumericTypes = new HashSet<Type>
    {
        typeof(int),
        typeof(int?),
        ...
    };

2
একটি ক্ষয়যোগ্য টাইপ কি আসলেই সংখ্যাসূচক? নাল আমার জ্ঞানের কোনও সংখ্যা নয়।
— ইলিডানএস 4 মনিকাকে

2
এটি আপনি কী অর্জন করতে চান তার উপর নির্ভর করে। আমার ক্ষেত্রে আমারও নালাগুলি অন্তর্ভুক্ত করা দরকার। তবে আমি এমন পরিস্থিতিতেও ভাবতে পারি যেখানে এটি পছন্দসই আচরণ নয়।
— জার্জেন স্টেইনব্লক

ভাল! সংখ্যার হিসাবে সংখ্যাটিকে চিকিত্সা করতে ইউআই ইনপুট বৈধতায় খুব দরকারী।
— guogangj

1
@ IllidanS4 চেকটি টাইপ করা আছে মান নয়। বেশিরভাগ ক্ষেত্রে নলযোগ্য সংখ্যার প্রকারগুলিকে সংখ্যা হিসাবে বিবেচনা করা উচিত। অবশ্যই যদি চেকটি মানটিতে ছিল এবং মানটি শূন্য হয়, তবে হ্যাঁ এটি সংখ্যা হিসাবে বিবেচনা করা উচিত নয়।
— নওফাল

40
public static bool IsNumericType(Type type)
{
  switch (Type.GetTypeCode(type))
  {
    case TypeCode.Byte:
    case TypeCode.SByte:
    case TypeCode.UInt16:
    case TypeCode.UInt32:
    case TypeCode.UInt64:
    case TypeCode.Int16:
    case TypeCode.Int32:
    case TypeCode.Int64:
    case TypeCode.Decimal:
    case TypeCode.Double:
    case TypeCode.Single:
      return true;
    default:
      return false;
  }
}

অপ্টিমাইজেশান সম্পর্কে নোট সরানো হয়েছে (এনজি মন্তব্য দেখুন) এবং আপনি যদি সত্যিই এটি অনুকূল করতে চান (পাঠযোগ্যতা এবং কিছু সুরক্ষা হারাতে ...):

public static bool IsNumericType(Type type)
{
  TypeCode typeCode = Type.GetTypeCode(type);
  //The TypeCode of numerical types are between SByte (5) and Decimal (15).
  return (int)typeCode >= 5 && (int)typeCode <= 15;
}


13
আমি জানি এই উত্তরটি পুরানো, তবে আমি সম্প্রতি এমন একটি স্যুইচটি পেয়েছি: প্রস্তাবিত অপ্টিমাইজেশন ব্যবহার করবেন না! আমি এই জাতীয় স্যুইচ থেকে উত্পন্ন আইএল কোডটি দেখেছিলাম এবং উল্লেখ করেছি যে সংকলকটি ইতিমধ্যে অপ্টিমাইজেশন প্রয়োগ করে (আইএল 5 তে টাইপ কোড থেকে বিয়োগ করা হয় এবং তারপর 0 থেকে 10 এর মানগুলি সত্য বলে বিবেচিত হয়)। অতএব এটি আরও বেশি পঠনযোগ্য এবং নিরাপদ এবং তত দ্রুতগতির জন্য স্যুইচটি ব্যবহার করা উচিত।
— enzi

1
আপনি যদি সত্যই এটি অনুকূল করতে চান এবং পঠনযোগ্যতার বিষয়ে চিন্তা না করেন তবে সর্বোত্তম কোডটি return unchecked((uint)Type.GetTypeCode(type) - 5u) <= 10u;এভাবে প্রবর্তিত শাখাটি সরিয়ে ফেলবে &&।
— আনোরজাকেন

14

মূলত স্কিটির সমাধান তবে আপনি নীচের মতো করে এটি পুনরায় ব্যবহার করতে পারেন:

public static class TypeHelper
{
    private static readonly HashSet<Type> NumericTypes = new HashSet<Type>
    {
        typeof(int),  typeof(double),  typeof(decimal),
        typeof(long), typeof(short),   typeof(sbyte),
        typeof(byte), typeof(ulong),   typeof(ushort),  
        typeof(uint), typeof(float)
    };

    public static bool IsNumeric(Type myType)
    {
       return NumericTypes.Contains(Nullable.GetUnderlyingType(myType) ?? myType);
    }
}

9

ফিলিপের প্রস্তাবের ভিত্তিতে পন্থা , এসফুন 28 এর প্রকারের জন্য অভ্যন্তরীণ প্রকারের চেক দিয়ে বর্ধিত Nullable:

public static class IsNumericType
{
    public static bool IsNumeric(this Type type)
    {
        switch (Type.GetTypeCode(type))
        {
            case TypeCode.Byte:
            case TypeCode.SByte:
            case TypeCode.UInt16:
            case TypeCode.UInt32:
            case TypeCode.UInt64:
            case TypeCode.Int16:
            case TypeCode.Int32:
            case TypeCode.Int64:
            case TypeCode.Decimal:
            case TypeCode.Double:
            case TypeCode.Single:
                return true;
            case TypeCode.Object:
                if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
                {
                    return Nullable.GetUnderlyingType(type).IsNumeric();
                    //return IsNumeric(Nullable.GetUnderlyingType(type));
                }
                return false;
            default:
                return false;
        }
    }
}

কেন এটা? প্রদত্ত Type typeএকটি সংখ্যার ধরণের কিনা তা আমাকে পরীক্ষা করে দেখতে হয়েছিল এবং স্বেচ্ছাসেবী object oসংখ্যাসূচক কিনা তা নয় ।


4

সি # 7 এর সাথে এই পদ্ধতিটি আমাকে সুইচ কেসের চেয়ে ভাল পারফরম্যান্স দেয় TypeCodeএবং HashSet<Type>:

public static bool IsNumeric(this object o) => o is byte || o is sbyte || o is ushort || o is uint || o is ulong || o is short || o is int || o is long || o is float || o is double || o is decimal;

টেস্টগুলি নিম্নলিখিত:

public static class Extensions
{
    public static HashSet<Type> NumericTypes = new HashSet<Type>()
    {
        typeof(byte), typeof(sbyte), typeof(ushort), typeof(uint), typeof(ulong), typeof(short), typeof(int), typeof(long), typeof(decimal), typeof(double), typeof(float)
    };

    public static bool IsNumeric1(this object o) => NumericTypes.Contains(o.GetType());

    public static bool IsNumeric2(this object o) => o is byte || o is sbyte || o is ushort || o is uint || o is ulong || o is short || o is int || o is long || o is decimal || o is double || o is float;

    public static bool IsNumeric3(this object o)
    {
        switch (o)
        {
            case Byte b:
            case SByte sb:
            case UInt16 u16:
            case UInt32 u32:
            case UInt64 u64:
            case Int16 i16:
            case Int32 i32:
            case Int64 i64:
            case Decimal m:
            case Double d:
            case Single f:
                return true;
            default:
                return false;
        }
    }

    public static bool IsNumeric4(this object o)
    {
        switch (Type.GetTypeCode(o.GetType()))
        {
            case TypeCode.Byte:
            case TypeCode.SByte:
            case TypeCode.UInt16:
            case TypeCode.UInt32:
            case TypeCode.UInt64:
            case TypeCode.Int16:
            case TypeCode.Int32:
            case TypeCode.Int64:
            case TypeCode.Decimal:
            case TypeCode.Double:
            case TypeCode.Single:
                return true;
            default:
                return false;
        }
    }
}

class Program
{
    static void Main(string[] args)
    {           
        var count = 100000000;

        //warm up calls
        for (var i = 0; i < count; i++)
        {
            i.IsNumeric1();
        }
        for (var i = 0; i < count; i++)
        {
            i.IsNumeric2();
        }
        for (var i = 0; i < count; i++)
        {
            i.IsNumeric3();
        }
        for (var i = 0; i < count; i++)
        {
            i.IsNumeric4();
        }

        //Tests begin here
        var sw = new Stopwatch();
        sw.Restart();
        for (var i = 0; i < count; i++)
        {
            i.IsNumeric1();
        }
        sw.Stop();

        Debug.WriteLine(sw.ElapsedMilliseconds);

        sw.Restart();
        for (var i = 0; i < count; i++)
        {
            i.IsNumeric2();
        }
        sw.Stop();

        Debug.WriteLine(sw.ElapsedMilliseconds);

        sw.Restart();
        for (var i = 0; i < count; i++)
        {
            i.IsNumeric3();
        }
        sw.Stop();

        Debug.WriteLine(sw.ElapsedMilliseconds);

        sw.Restart();
        for (var i = 0; i < count; i++)
        {
            i.IsNumeric4();
        }
        sw.Stop();

        Debug.WriteLine(sw.ElapsedMilliseconds);
    }

3

আপনি Type.IsPrimitive ব্যবহার করতে পারেন এবং তারপরে Booleanএবং Charপ্রকারগুলি বাছাই করুন , এরকম কিছু:

bool IsNumeric(Type type)
{
    return type.IsPrimitive && type!=typeof(char) && type!=typeof(bool);
}

সম্পাদনা : আপনি সংখ্যক হিসাবে বিবেচনা না করে আপনি প্রকার IntPtrএবং UIntPtrপ্রকারগুলিও বাদ দিতে চাইতে পারেন।


1
সুতরাং decimalটাইপ সংখ্যাটি নয়?
— লুক এইচ

ওফস ... ঠিক আছে, মনে হচ্ছে গিলাইমের সমাধান সর্বোত্তম is
— কোনামিমন

3

নাল-টাইপ সমর্থন সহ এক্সটেনশন টাইপ করুন।

public static bool IsNumeric(this Type type)
    {
        if (type == null) { return false; }

        if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
        {
            type = type.GetGenericArguments()[0];
        }

        switch (Type.GetTypeCode(type))
        {
            case TypeCode.Byte:
            case TypeCode.SByte:
            case TypeCode.UInt16:
            case TypeCode.UInt32:
            case TypeCode.UInt64:
            case TypeCode.Int16:
            case TypeCode.Int32:
            case TypeCode.Int64:
            case TypeCode.Decimal:
            case TypeCode.Double:
            case TypeCode.Single:
                return true;
            default:
                return false;
        }
    }

1

সংক্ষিপ্ত উত্তর: না

দীর্ঘ উত্তর: না।

আসল বিষয়টি হ'ল সি # তে বিভিন্ন ধরণের সংখ্যক ডেটা থাকতে পারে। আপনি কী আশা করবেন তা না জানা থাকলে (ইনট, ডাবল ইত্যাদি) আপনার "লং" কেস স্টেটমেন্টটি ব্যবহার করা দরকার।


1

এটি পাশাপাশি কাজ করতে পারে। তবে আপনি এটিকে কোনও প্রকারের সাথে অনুসরণ করতে চাইতে পারেন after পরবর্তীতে আপনি যেভাবে চান তা কাস্ট করতে পার্স করুন।

public bool IsNumeric(object value)
{
    float testValue;
    return float.TryParse(value.ToString(), out testValue);
}

1

সংশোধিত স্কিট এবং arviman এর সমাধান ব্যবহার Generics, Reflectionএবং C# v6.0।

private static readonly HashSet<Type> m_numTypes = new HashSet<Type>
{
    typeof(int),  typeof(double),  typeof(decimal),
    typeof(long), typeof(short),   typeof(sbyte),
    typeof(byte), typeof(ulong),   typeof(ushort),
    typeof(uint), typeof(float),   typeof(BigInteger)
};

অনুসরণ করেছেন:

public static bool IsNumeric<T>( this T myType )
{
    var IsNumeric = false;

    if( myType != null )
    {
        IsNumeric = m_numTypes.Contains( myType.GetType() );
    }

    return IsNumeric;
}

এর জন্য ব্যবহার (T item):

if ( item.IsNumeric() ) {}

null মিথ্যা প্রত্যাবর্তন


1

স্যুইচটি কিছুটা ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে খারাপ সময়কালে পদ্ধতিগুলি সমস্ত ধরণের মধ্য দিয়ে যাবে। আমি মনে করি, ডিক্টোনারি ব্যবহার করা আরও দুর্দান্ত, এই পরিস্থিতিতে আপনারা থাকবেন O(1):

public static class TypeExtensions
{
    private static readonly HashSet<Type> NumberTypes = new HashSet<Type>();

    static TypeExtensions()
    {
        NumberTypes.Add(typeof(byte));
        NumberTypes.Add(typeof(decimal));
        NumberTypes.Add(typeof(double));
        NumberTypes.Add(typeof(float));
        NumberTypes.Add(typeof(int));
        NumberTypes.Add(typeof(long));
        NumberTypes.Add(typeof(sbyte));
        NumberTypes.Add(typeof(short));
        NumberTypes.Add(typeof(uint));
        NumberTypes.Add(typeof(ulong));
        NumberTypes.Add(typeof(ushort));
    }

    public static bool IsNumber(this Type type)
    {
        return NumberTypes.Contains(type);
    }
}

1

ব্যবহার করে দেখুন TypeSupport C # এর জন্য nuget প্যাকেজ। এটিতে সমস্ত সংখ্যার প্রকারগুলি সনাক্ত করার জন্য সমর্থন রয়েছে (অন্যান্য অনেক বৈশিষ্ট্যের মধ্যে):

var extendedType = typeof(int).GetExtendedType();
Assert.IsTrue(extendedType.IsNumericType);

আমি এই প্যাকেজটি জানতাম না। ওপিতে অনুরোধ করা ধরণের অপারেশনের জন্য আমাদের নিজস্ব কোড লিখতে এড়াতে অনেক ক্ষেত্রে জীবন রক্ষাকারী বলে মনে হয়। ধন্যবাদ!
— আফ্রিক্ট করুন

0

দুর্ভাগ্যক্রমে এই ধরণের সমস্ত মান ধরণের ব্যতীত আর তেমন একটা মিল নেই। তবে দীর্ঘ স্যুইচ-কেস এড়াতে আপনি এই সমস্ত ধরণের সাথে কেবল একটি পঠনযোগ্য তালিকাটি সংজ্ঞায়িত করতে পারেন এবং তারপরে প্রদত্ত প্রকারটি তালিকার ভিতরে রয়েছে কিনা তা পরীক্ষা করে দেখতে পারেন।


0

এগুলি সমস্ত মান ধরণের (বুল এবং সম্ভবত এনাম বাদে)। সুতরাং আপনি সহজভাবে ব্যবহার করতে পারেন:

bool IsNumberic(object o)
{
    return (o is System.ValueType && !(o is System.Boolean) && !(o is System.Enum))
}

1
এটি কোনও ব্যবহারকারীর সংজ্ঞায়িত হয়ে সত্য হয়ে উঠবে struct... আমি মনে করি না এটি আপনি চান।
— ড্যান তাও

1
আপনি সঠিক. অন্তর্নির্মিত সংখ্যাযুক্ত প্রকারগুলি পাশাপাশি স্ট্রোকগুলিও। তাই আদিম তুলনা সঙ্গে ভাল তারপর যেতে।
— মান্দোম্যান্ডো

0

সম্পাদনা: ঠিক আছে, আমি আরও পারফরম্যান্ট হতে নীচের কোডটি সংশোধন করেছি এবং তারপরে @ হুগো পোস্ট করা পরীক্ষাগুলি এর বিরুদ্ধে চালিয়েছি। গতি @ হুগো এর আইএফ তার অনুক্রমের শেষ দশক (দশমিক) ব্যবহার করে সমান হয়। তবে যদি প্রথম আইটেমটি 'বাইট' ব্যবহার করেন তবে তিনি তার পিষ্টকটি গ্রহণ করেন, তবে পারফরম্যান্সের ক্ষেত্রে বিষয়টি পরিষ্কারভাবে অর্ডার করুন। যদিও নীচের কোডটি ব্যবহার করা আরও সহজ এবং এটির দামের সাথে আরও সামঞ্জস্যপূর্ণ, তবে এটি রক্ষণাবেক্ষণযোগ্য বা ভবিষ্যতের প্রমাণ-সক্ষম নয়।

টাইপ.গেটটাইপকোড () থেকে কনভার্ট.গেটটাইপকোড () থেকে পরিবর্তন প্রায় 25%, ভিএস এনাম.পার্স () যা 10 গুণ ধীর গতির মত পারফরম্যান্সকে দ্রুতগতিতে দেখায় like


আমি জানি এই পোস্টটি পুরানো তবে যদি টাইপকোড এনাম পদ্ধতিটি ব্যবহার করা হয় তবে সবচেয়ে সহজ (এবং সম্ভবত সবচেয়ে সস্তা) এরকম কিছু হবে:

public static bool IsNumericType(this object o)
{   
  var t = (byte)Convert.GetTypeCode(o);
  return t > 4 && t < 16;
}

টাইপকোডের জন্য নিম্নলিখিত এনাম সংজ্ঞা দেওয়া:

public enum TypeCode
{
    Empty = 0,
    Object = 1,
    DBNull = 2,
    Boolean = 3,
    Char = 4,
    SByte = 5,
    Byte = 6,
    Int16 = 7,
    UInt16 = 8,
    Int32 = 9,
    UInt32 = 10,
    Int64 = 11,
    UInt64 = 12,
    Single = 13,
    Double = 14,
    Decimal = 15,
    DateTime = 16,
    String = 18
}

আমি এটি পুরোপুরি পরীক্ষা করে দেখিনি, তবে মৌলিক সি # সংখ্যাগত ধরণের জন্য, এটি এটি আবৃত মনে হবে। যাইহোক, @ জোনস্কিট যেমন উল্লেখ করেছেন, এই এনামটি .NET রাস্তায় যোগ করা অতিরিক্ত ধরণের জন্য আপডেট করা হয়নি।


-1

ওহো! প্রশ্ন ভুল! ব্যক্তিগতভাবে, স্কিটির সাথে রোল করবে ।


এইচআরএম, শোনাচ্ছে আপনি নিজের ডেটা DoSomethingচালু করতে চান Type। আপনি যা করতে পারেন তা নীচে রয়েছে

public class MyClass
{
    private readonly Dictionary<Type, Func<SomeResult, object>> _map = 
        new Dictionary<Type, Func<SomeResult, object>> ();

    public MyClass ()
    {
        _map.Add (typeof (int), o => return SomeTypeSafeMethod ((int)(o)));
    }

    public SomeResult DoSomething<T>(T numericValue)
    {
        Type valueType = typeof (T);
        if (!_map.Contains (valueType))
        {
            throw new NotSupportedException (
                string.Format (
                "Does not support Type [{0}].", valueType.Name));
        }
        SomeResult result = _map[valueType] (numericValue);
        return result;
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.