函数IIF,如何使其采用逻辑表达式的2N + 1个参数?,C#



在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"。 但那将是一个坏主意,不是吗?

最新更新