在Visual Basic中,有这个IIF函数,如Crystal Report等...
在 C# 本身中,此函数不存在,但它与执行以下操作相同:
bool a = true;
string b = a ? "is_True" : "is_False";
但是为了使代码更容易阅读,我想将其作为 C# 的函数,如下所示:
public static T IIf<T>(bool expression, T truePart, T falsePart)
{
return expression ? truePart : falsePart;
}
或者不使用实际值进行操作也可以使用委托来完成,以访问必要的值:
public static T IIf<T>(bool expression, Func<T> truePart, Func<T> falsePart)
{
return expression ? truePart() : falsePart();
}
到目前为止,这效果很好...
但是我如何修改这个函数,以便我可以接受 2N + 1 个参数?
(N - 指定的逻辑表达式数)
示例所需的结果:
每个奇数参数指定一个逻辑表达式;
每个偶数参数指定在前一个表达式的计算结果为 true 时返回的值;
最后一个参数指定在先前计算的逻辑表达式生成 false 时返回的值。
int value = IIf(Name = "Joel", 1, Name = "Peter", 2, Name = "Maria", 3, 4);
有人可以帮我一把吗?
环境:C # - Visual Studio 2017
首先,正如评论中所指出的,这是一个坏主意。较新版本的 C# 已支持模式匹配开关作为该语言的内置功能;使用它。
其次,这是一个坏主意,因为"参数,案例1,结果1,案例2,结果2,..."的API是具有在 C# 类型系统中难以表达的签名。
如果我被迫实现这样的 API,我建议使用元组:
public static R Switch<A, R>(
A item,
R theDefault,
params (A, R)[] cases )
{
foreach(var c in cases)
if (item.Equals(c.Item1))
return c.Item2;
return theDefault;
}
或者,创建一个有用的实用程序方法并使用它:
public static T FirstOrDefault(
this IEnumerable<T> items,
T theDefault,
Func<T, bool> predicate)
{
foreach(var i in items.Where(predicate))
return i;
return theDefault;
}
public static R Switch<A, R>(
A item,
R theDefault,
params (A, R)[] cases ) =>
cases.FirstOrDefault(
(item, theDefault),
c => item.Equals(c.Item1)).Item2;
如果由于使用的是旧版本的 C#而无法使用元组,则可以创建自己的对类型或使用键值对类型。
但只是不要去那里。如果需要开关,请编写开关。如果你需要字典,写一个字典。
如果你想保留参数的顺序,如果你想让函数复制你在其他地方看到的东西,那么你大概会这样做,那么你可以写这样的东西:
public T IIf<T>(params object[] objects) {
for(var i = 0; i < objects.Length - 1; i += 2)
if((bool)objects[i])
return (T)objects[i+1];
return (T)objects[objects.Length - 1];
}
但这是一个很好的教训,说明为什么你会避免这样的事情。 首先,您必须显式声明正在使用的类型。 所以你必须像这样使用它:
var value = IIf<int>(Name == "Joel", 1, Name == "Peter", 2, Name == "Maria", 3, 4);
请注意将"int"作为类型参数传递。 您可以通过更改参数的顺序来避免这种情况,以便默认值排在第一位。
但是,如果你只是愿意采用个人模式,嵌套的三元语法可以非常易读:
var value =
Name == "Joel" ? 1
: Name == "Peter" ? 2
: Name == "Maria" ? 3
: 4;
如果你觉得它不可读,那只是因为它需要一些时间来适应。 想象一下,从C#开发人员到VB,然后看到"IIF"。 你会想,"为什么他们在'IF'中添加额外的'I'? 我应该创建一个模拟"IIF"的函数"IF"。 但那将是一个坏主意,不是吗?