【问题标题】:C# - Limiting scope to ternary statementC# - 将范围限制为三元语句
【发布时间】:2017-02-14 16:48:42
【问题描述】:

编辑:最初,这篇文章的示例处理的是哈希码,所以您会看到一些 cmets 使用 param.GetHashCode(),而不是 (1+param)。为了更深入地了解这一点,我更改了函数来计算某个数字的绝对值加一。

假设我想创建一个计算某个整数的绝对值的函数(不使用 Math.Abs​​)。我可以写类似的东西:

int absoluteValueOfOnePlus(int param)
{
    int onePlusParam= 1 + param;
    return ((onePlusParam> 0) ? (onePlusParam) : (-onePlusParam) );
}

我希望将 onePlusParm 的范围限制在三元语句内——类似于:

int absoluteValueOfOnePlus(intparam)
{
    return (((int onePlusParam = 1 + param) > 0) ? (onePlusParam) : (-onePlusParam) );
}

我知道这不是有效的 C#,但它证明了我正在尝试执行的一个很好的示例 - 创建一些仅存在于三元运算符范围内的变量。

【问题讨论】:

  • “我希望将此方法压缩到一行”。你能解释一下为什么需要这样做吗?
  • 你可以做到int i; return i = param.GetHashCode() > 0 ? i : -i; ...我不会,但你可以。
  • @openshac,它更多的是关于限制范围而不是其他任何东西。如果函数更大,我将存在于函数的其余部分。在三元语句中使用声明会将范围限制在三元语句内——语句完成后,将删除 i。
  • @MatthewWhited,也好不到哪里去。我的目标是限制 i 的范围。将计算移到三元语句中仍然使 i 在函数范围内,而不是三元语句。
  • 您可以使用{ ... } 创建一个范围块。块内的任何内容都将超出块外的范围。

标签: c# ternary-operator


【解决方案1】:

三元表达式的部分是表达式。如果语言设计者要允许您要求的内容,他们可能会为所有表达式而不是仅针对三元表达式这样做。然后你也可以if ((int n = foo()) != 0) bar(n);

在 C# 中,声明是语句,而不是表达式。所以答案是否定的,你不能这样做。但是,for 语句可以接受声明,因此最接近单个语句的是:

for (int i = param.GetHashCode();;)
    return (i > 0) ? i : -i;

这在技术上是一个单一的语句,尽管是一个复合语句,并且在两行上。但这看起来很糟糕的代码,我不会那样写的。

如果您主要关心的是最小化i 的范围,那么请使用较小的范围:

int positiveHash(string param)
{
    // Some statements here...
    // ...

    // Start a small scope
    {
        int i = param.GetHashCode();
        if (...)
            return ((i > 0) ? (i) : (-i) );
    }

    // Some more C# statements here.
    // i is out of scope here.
}

【讨论】:

  • 感谢您的解释。我的问题的目标是限制 i 的范围——不一定是干净的代码,所以这是完美的。
【解决方案2】:

我只想写:

int GetPositiveHash(string param)
{
    return Math.Abs(param.GetHashCode());
}

int GetPositiveHash(string param)
{
    int hashCode = param.GetHashCode();

    return Math.Abs(hashCode);
}

辅助可读性、可维护性,更重要的是在这种情况下避免premature optimization which is the root of all evil

如果您真的担心性能问题,请分析您的代码并查看您最大的瓶颈在哪里。如果GetPosiitiveHash() 造成了最大的瓶颈,我会感到惊讶。

您可能想看看.Net Framework source codeString.GetHashCode()。您会看到,与 GetHashCode() 方法内部发生的情况相比,三元运算符的节省将非常少。

值得记住:

这句话的完整版是“我们应该忘记小 效率,大约 97% 的时间:过早优化是 万恶之根。”我同意这一点。它通常不值得 在明显的位置之前花费大量时间对代码进行微优化 性能瓶颈是。

来自The fallacy of premature optimization

【讨论】:

  • 我给出的概念更多的是一个例子。我正在探索将变量的范围限制在三元语句内——不一定优化我提供的确切代码块。话虽如此,这绝对是一个值得记住的报价。
  • 好的,可能值得修改你的问题,用一些微不足道的东西替换 GetHashCode(),它掩盖了你试图实现的优化。
  • 在原始帖子的底部添加更新部分可能更容易,这样现有的回复就不会过时。
【解决方案3】:

您可以将范围内的数据变量 (i) 替换为范围内的函数变量。优点是函数更有可能只编写一次,并且不太可能被滥用。

int positiveHash(string param)
{
    Func<int, int> absoluteValue = i => (i > 0) ? i : -1;

    return absoluteValue(param.GetHashCode());
}

【讨论】:

  • 我对 lambda 表达式的经验有限,但我喜欢这个。我会更多地研究函数变量——谢谢。
【解决方案4】:

我的尝试

static int positiveHash(string param)
{
     return new List<string>() {param}.Select(s => s.GetHashCode()).Select(i => (i > 0) ? (i) : (-i)).Single();
}

(当然你的代码(和我的)不好,你需要把你的方法分成两个更小的方法)

以及更新后的问题

static int absoluteValueOfOnePlus(int intparam)
{
        return new List<int> { intparam }.Select(n => n + 1).Select(i => (i > 0) ? (i) : (-i)).Single();
}

【讨论】:

    【解决方案5】:

    除了创建一个新块之外,您还可以使用内置的绝对值函数Math.Abs(...) 或定义自己的 lambda/函数;

    ...内置...

    public static int hash(string param)
    {
        return Math.Abs(param.GetHashCode());
    }
    

    ... 拉姆达 ...

    static Func<int, int> abs = i => i > 0 ? i : -i;
    public static int hash(string param)
    {
        return abs(param.GetHashCode());
    }
    

    ...静态函数...

    static int Abs(int i)
    {
        return i > 0 ? i : -i;
    }
    public static int hash(string param)
    {
        return Abs(param.GetHashCode());
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-30
      • 2013-05-30
      • 2016-05-31
      • 1970-01-01
      • 2014-03-20
      相关资源
      最近更新 更多