很多時候,會判斷一個值是否為數值類型,數值類型是可以進行算術運算的,表示格式也比較統一,是以在做通用功能時會用到。下面給出了幾種用法。
第一版:通用用法,設定具體類型逐一進行判斷,這種做法可以靈活設定類型,缺點也是想增加類型,也得人工增加。
bool IsDig(object t) => t switch { short => true, int => true, long => true, Int128 => true, double => true, float => true, Half => true, decimal => true, ushort => true, uint => true, ulong => true, UInt128 => true, _ => false, }; Console.WriteLine("--------嫡系---------"); Half h = (Half)43210.123456789; Console.WriteLine($"{h.GetType().Name},{IsDig(h)}"); var f = 1.2f; Console.WriteLine($"{f.GetType().Name},{IsDig(f)}"); var d = 1.2d; Console.WriteLine($"{d.GetType().Name},{IsDig(d)}"); var dec = 1.2m; Console.WriteLine($"{dec.GetType().Name},{IsDig(dec)}"); ushort us = 10; Console.WriteLine($"{us.GetType().Name},{IsDig(us)}"); uint ui = 10; Console.WriteLine($"{ui.GetType().Name},{IsDig(ui)}"); ulong ul = 10; Console.WriteLine($"{ul.GetType().Name},{IsDig(ul)}"); UInt128 ubi = 1020232321211; Console.WriteLine($"{ubi.GetType().Name},{IsDig(ubi)}"); short si = 10; Console.WriteLine($"{si.GetType().Name},{IsDig(si)}"); int i = 10; Console.WriteLine($"{i.GetType().Name},{IsDig(i)}"); long l = 10; Console.WriteLine($"{l.GetType().Name},{IsDig(l)}"); Int128 bi = 1020232321211; Console.WriteLine($"{bi.GetType().Name},{IsDig(bi)}"); Console.WriteLine("--------本家---------"); BigInteger bgi = 12313213213213212; Console.WriteLine($"{bgi.GetType().Name},{IsDig(bgi)}"); Console.WriteLine("---------娘家--------"); char c = 'c'; Console.WriteLine($"{c.GetType().Name},{IsDig(c)}"); var b = (byte)1; Console.WriteLine($"{b.GetType().Name},{IsDig(b)}"); Console.WriteLine("--------外人---------"); var t = true; Console.WriteLine($"{t.GetType().Name},{IsDig(t)}"); var str = "abcd"; Console.WriteLine($"{str.GetType().Name},{IsDig(str)}");
結果:
方案二:在.NET 7中,官方引入了一個INumber的接口,實作了這個接口的簡單類型,都是官方規定的數值類型,借助這一點,可以判斷是否是數值類型。
bool IsDig(object t) { return typeof(INumber<>).IsInstanceOfType(t); }
結果:
方案三:有的時候,我們會用到BigInteger這個新的表示大數值的類型,但如果用方案二,這個類型就沒有算在其中,那又想把它算在數值類型中,就得另謀出路了。
bool IsDig(object t) { return t.GetType().GetInterfaces().Any(s => s.Name == typeof(INumber<>).Name); }
結果:
上面三種方式都是實作判斷數值類型的,但它們的性能如何呢?下面做了個簡單對比:
public class TestIsDIg { object[] datas; public TestIsDIg() { datas = new object[] { 1, 1l, 1d, 1f, 1m }; } [Benchmark] public bool IsDig3() { var result = true; foreach (var t in datas) { result = result && t.GetType().GetInterfaces().Any(s => s.Name == typeof(INumber<>).Name); } return result; } [Benchmark] public bool IsDig2() { var result = true; foreach (var t in datas) { return typeof(INumber<>).IsInstanceOfType(t); } return result; } [Benchmark] public bool IsDig1() { var result = true; foreach (var t in datas) { return IsDig(t); } return result; bool IsDig(object t) => t switch { short => true, int => true, long => true, Int128 => true, double => true, float => true, Half => true, decimal => true, ushort => true, uint => true, ulong => true, UInt128 => true, _ => false, }; } }
結果:
看來方案一還是靠譜的,方案三是最不靠譜的,方案二可以說是成本效益較好的。