[英]Switch case and generics checking
I want to write a function that format int
and decimal
differently into string我想编写一个函数,将
int
和decimal
不同的方式格式化为字符串
I have this code:我有这个代码:
and I want to rewrite it to generics:我想将其重写为泛型:
public static string FormatAsIntWithCommaSeperator(int value)
{
if (value == 0 || (value > -1 && value < 1))
return "0";
return String.Format("{0:#,###,###}", value);
}
public static string FormatAsDecimalWithCommaSeperator(decimal value)
{
return String.Format("{0:#,###,###.##}", value);
}
public static string FormatWithCommaSeperator<T>(T value) where T : struct
{
string formattedString = string.Empty;
if (typeof(T) == typeof(int))
{
if ((int)value == 0 || (value > -1 && value < 1))
return "0";
formattedString = String.Format("{0:#,###,###}", value);
}
//some code...
}
/// <summary>
/// If the number is an int - returned format is without decimal digits
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static string FormatNumberTwoDecimalDigitOrInt(decimal value)
{
return (value == (int)value) ? FormatAsIntWithCommaSeperator(Convert.ToInt32(value)) : FormatAsDecimalWithCommaSeperator(value);
}
How can i use T in the function body?如何在函数体中使用 T?
What syntax should I use?我应该使用什么语法?
In modern C#:在现代 C# 中:
public static string FormatWithCommaSeperator<T>(T value) where T : struct
{
switch (value)
{
case int i:
return $"integer {i}";
case double d:
return $"double {d}";
}
}
Another way to do switch on generic is:另一种打开泛型的方法是:
switch (typeof(T))
{
case Type intType when intType == typeof(int):
...
case Type decimalType when decimalType == typeof(decimal):
...
default:
...
}
Note that when
as a case guard in switch
expressions was introduced in C# 7.0 /Visual Studio 2017.需要注意的是
when
在一个外壳安全switch
表达式在C#7.0中引入/ Visual Studio的2017年。
DoFormat(int value)
{
}
DoFormat(double value)
{
}
If you insist on using generics:如果你坚持使用泛型:
switch (value.GetType().Name)
{
case "Int32":
break;
case "Double":
break;
default:
break;
}
OR或者
if (value is int)
{
int iValue = (int)(object)value;
}
else if (value is double)
{
double dValue = (double)(object)value;
}
else
{
}
I had a similar question, but with custom classes rather than built-in data types.我有一个类似的问题,但使用自定义类而不是内置数据类型。 Here's how I went about it:
以下是我的处理方式:
switch (typeof(T).Name)
{
case nameof(Int32):
break;
case nameof(Decimal):
break;
}
I modified it to use the types you are using (ie, int and decimal).我修改它以使用您正在使用的类型(即,int 和decimal)。 I like this approach more than hard coding strings, as a refactor of a class name will not break this code.
我比硬编码字符串更喜欢这种方法,因为类名的重构不会破坏这段代码。
With newer versions of C#, you could also do this some of the time:使用较新版本的 C#,您有时也可以这样做:
switch (Activator.CreateInstance(typeof(T)))
{
case int _:
break;
case decimal _:
break;
}
I say "some of the time" because that would only really work with types that have a default constructor.我说“有时”是因为那只适用于具有默认构造函数的类型。 This approach uses pattern matching and discards.
这种方法使用模式匹配和丢弃。 I don't really like it since you need to create an instance of the object (that you then throw away) and because of the default constructor requirement.
我真的不喜欢它,因为您需要创建对象的实例(然后将其丢弃)并且因为默认构造函数要求。
more formatted way to do switch on generic is:开启泛型的更格式化的方法是:
switch (true)
{
case true when typeof(T) == typeof(int):
...
case true when typeof(T) == typeof(decimal):
...
default:
...
}
In C# 8 you can use (replace "..." with the relevant code):在C# 8 中,您可以使用(用相关代码替换“...”):
... type switch
{
Type _ when type == typeof(int) => ...,
Type _ when type == typeof(decimal) => ...,
_ => ... // default case
};
Another elegant option (replace "..." with the relevant code):另一个优雅的选择(用相关代码替换“...”):
... Type.GetTypeCode(type) switch
{
TypeCode.Int32 => ...,
TypeCode.Decimal => ...,
_ => ...
};
For more info: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/switch-expression有关更多信息: https : //docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/switch-expression
Alternatively you could always do:或者,您可以随时执行以下操作:
public static string FormatWithCommaSeparator<T>(T[] items)
{
var itemArray = items.Select(i => i.ToString());
return string.Join(", ", itemArray);
}
You could check the type of the variabele;您可以检查变量的类型;
public static string FormatWithCommaSeperator<T>(T value)
{
if (value is int)
{
// Do your int formatting here
}
else if (value is decimal)
{
// Do your decimal formatting here
}
return "Parameter 'value' is not an integer or decimal"; // Or throw an exception of some kind?
}
You could instead of using generics use IConvertible你可以代替使用泛型使用 IConvertible
public static string FormatWithCommaSeperator(IConvertible value) { IConvertible convertable = value as IConvertible; if(value is int) { int iValue = convertable.ToInt32(null); //Return with format. } ..... }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.