-1

在 Visual Basic 中,有这个IIF Function,如 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 - 指定的逻辑表达式的数量)

示例所需的结果:

每个奇数参数指定一个逻辑表达式;

每个偶数参数指定前一个表达式计算结果为真时返回的值;

最后一个参数指定如果先前评估的逻辑表达式产生假时返回的值。

int value = IIf(Name = "Joel", 1, Name = "Peter", 2, Name = "Maria", 3, 4);

有人可以帮我解决这个问题吗?

环境:C#-Visual Studio 2017

4

2 回答 2

6

首先,正如评论中所指出的,这是一个坏主意。较新版本的 C# 已经支持模式匹配开关作为语言的内置功能;用它。

其次,这是一个坏主意,因为“argument, case1, result1, case2, result2, ...”的 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# 而无法使用元组,则可以创建自己的对类型或使用键值对类型。

但不要去那里。如果你需要一个开关,写一个开关。如果你需要一本字典,就写一本字典。

于 2019-07-22T21:16:55.477 回答
1

如果您想保留参数的顺序,如果您努力使函数复制您在其他地方看到的内容,那么您可能会这样做,那么您可以编写如下内容:

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

于 2019-07-22T21:23:14.703 回答