我想写一个格式化的函数int和decimal不同的字符串
我有这个代码:
我想把它重写为泛型:
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);
}
Run Code Online (Sandbox Code Playgroud)
我如何在函数体中使用T?
我应该使用什么语法?
Nik*_*vić 38
您可以使用TypeCode进行切换:
switch (Type.GetTypeCode(typeof(T)))
{
case TypeCode.Int32:
break;
case TypeCode.Decimal:
break;
}
Run Code Online (Sandbox Code Playgroud)
fla*_*am3 27
另一种打开泛型的方法是:
switch (typeof(T))
{
case Type intType when intType == typeof(int):
...
case Type decimalType when decimalType == typeof(decimal):
...
default:
...
}
Run Code Online (Sandbox Code Playgroud)
请注意,在 C# 7.0 /Visual Studio 2017 中引入when了switch表达式中的 case 保护。
Nic*_*tby 18
我有一个类似的问题,但是使用自定义类而不是内置数据类型。我是这样做的:
switch (typeof(T).Name)
{
case nameof(Int32):
break;
case nameof(Decimal):
break;
}
Run Code Online (Sandbox Code Playgroud)
我修改它以使用您正在使用的类型(即 int 和decimal)。与硬编码字符串相比,我更喜欢这种方法,因为类名的重构不会破坏此代码。
使用较新版本的 C#,您有时也可以执行此操作:
switch (Activator.CreateInstance(typeof(T)))
{
case int _:
break;
case decimal _:
break;
}
Run Code Online (Sandbox Code Playgroud)
我说“有时”是因为这只适用于具有默认构造函数的类型。该方法使用模式匹配和丢弃。我不太喜欢它,因为您需要创建对象的实例(然后将其丢弃)并且由于默认构造函数的要求。
Tam*_*ely 11
在现代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}";
}
}
Run Code Online (Sandbox Code Playgroud)
如果您有对象,则可以使用 C# 7模式匹配。但是,如果您没有对象并希望启用泛型类型 T,那么最好、最快的解决方案就是三元if运算符。
public string TernaryIf<T>() =>
typeof(T) == typeof(int) ? "#,###,###" :
typeof(T) == typeof(decimal) ? "#,###,###.##" :
null;
public string TrueSwitch<T>() =>
true switch
{
true when typeof(T) == typeof(int) => "#,###,###",
true when typeof(T) == typeof(decimal) => "#,###,###.##",
_ => null,
};
public string DefaultSwitch<T>() =>
default(T) switch
{
int => "#,###,###",
decimal => "#,###,###.##",
_ => null,
};
public string When_Switch<T>() =>
typeof(T) switch
{
Type _ when typeof(T) == typeof(int) => "#,###,###",
Type _ when typeof(T) == typeof(decimal) => "#,###,###.##",
_ => null,
};
public string TypeCodeSwitch<T>() =>
Type.GetTypeCode(typeof(T)) switch
{
TypeCode.Int32 => "#,###,###",
TypeCode.Decimal => "#,###,###.##",
_ => null,
};
public string WhenSwitch<T>() =>
typeof(T) switch
{
Type intType when intType == typeof(int) => "#,###,###",
Type decimalType when decimalType == typeof(decimal) => "#,###,###.##",
_ => null,
};
public string NameOfSwitch<T>() =>
typeof(T).Name switch
{
nameof(Int32) => "#,###,###",
nameof(Decimal) => "#,###,###.##",
_ => null,
};
public string ActivatorSwitch<T>() =>
Activator.CreateInstance(typeof(T)) switch
{
int => "#,###,###",
decimal => "#,###,###.##",
_ => null,
};
Run Code Online (Sandbox Code Playgroud)
基准:
| 方法 | 时间 |
|---|---|
| 三元If | 0.37纳秒 |
| 真开关 | 0.37纳秒 |
| 默认开关 | 0.48纳秒 |
| When_Switch | 1.92纳秒 |
| 类型代码开关 | 3.85纳秒 |
| 何时切换 | 3.96纳秒 |
| 交换机名称 | 7.98纳秒 |
| 激活开关 | 12.10纳秒 |
DoFormat(int value)
{
}
DoFormat(double value)
{
}
Run Code Online (Sandbox Code Playgroud)
如果您坚持使用泛型:
switch (value.GetType().Name)
{
case "Int32":
break;
case "Double":
break;
default:
break;
}
Run Code Online (Sandbox Code Playgroud)
或者
if (value is int)
{
int iValue = (int)(object)value;
}
else if (value is double)
{
double dValue = (double)(object)value;
}
else
{
}
Run Code Online (Sandbox Code Playgroud)
switch ((Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T)).Name)
{
case nameof(Int32):
...
case nameof(Decimal):
...
case nameof(Boolean): // You can also switch types like 'bool' or Nullable 'bool?'
...
case nameof(String): // Why not to use 'string'?
...
default:
...
}
Run Code Online (Sandbox Code Playgroud)
如果您更喜欢switch 表达式,您可以使用:
return (Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T)).Name switch
{
nameof(Int32) => ...,
nameof(Decimal) => ...,
nameof(Boolean) => ..., // You can also switch types like 'bool' or Nullable 'bool?'
nameof(String) => ..., // Why not to use 'string'?
_ => ...,
};
Run Code Online (Sandbox Code Playgroud)
切换通用的更格式化的方法是:
switch (true)
{
case true when typeof(T) == typeof(int):
...
case true when typeof(T) == typeof(decimal):
...
default:
...
}
Run Code Online (Sandbox Code Playgroud)