【问题标题】:C# - Referencing "this int" parameterC# - 引用“this int”参数
【发布时间】:2016-08-16 12:31:39
【问题描述】:



我有非常简单的按位运算符方法,我想像这样使用:

myInt.SetBit(int k, bool set)

所以它将索引“k”处的位更改为值“set”(0 或 1)我首先想到的是这样做:

public static void SetBit(this int A, int k, bool set) { 
    if (set) A |= 1 << k; 
    else A &= ~(1 << k); 
}

但这当然只会改变变量“A”的内部值,而不是原始变量,因为整数不是引用类型。
我不能将 'ref' 与 'this' 一起使用,所以我不知道如何将其转换为参考参数。
我已经为 Int 数组提供了类似的方法,但是由于数组是引用类型,所以这些方法可以正常工作。

我正在寻找一种方法来为单个整数保留这种方便的语法,如果有的话。

【问题讨论】:

  • 将您的签名从void 更改为int 并返回新值。

标签: c# int bit-manipulation this ref


【解决方案1】:

您不应将其视为引用类型。

让您的方法返回修改后的值并将其分配回您的变量。这种方法将与不可变类型一致。考虑String.Replace 的示例,它不会就地修改字符串,而是返回修改后的副本。

public static int SetBit(this int A, int k, bool set)
{
    if (set) A |= 1 << k;
    else A &= ~(1 << k);

    return A;
}

【讨论】:

  • 感谢您的快速答复!这很有意义,尽管它将语法更改为 myInt = myInt.SetBit(parameters) 而不是简单地让 myInt.SetBit(parameters) 自己工作。我希望保持简单的语法,但我认为更改它可能是必要的,这听起来确实是最好的解决方案。
【解决方案2】:

某些类型(如ints)是不可变的,这意味着一旦将它们设置为一个值,就不能再次更改它们。您会注意到,任何处理 int 的方法都将返回一个新的 int,而不是更改给定值的值。

像这样更新你的代码:

public static int SetBit(this int A, int k, bool set) { 
    if (set) A |= 1 << k; 
    else A &= ~(1 << k); 
    return A;
}

并像这样使用它:

var x = 5;
x = x.SetBit(1, true);

【讨论】:

  • 你会注意到任何处理 int 的方法都会返回一个新的 int 而不是改变给定值的值 - 除了带有 ref int 参数的方法...
  • 呃,不。 x++呢?
  • x++ 是 x += 1 的语义糖,它是 x = x + 1 的语义糖。
  • @Glubus,实际上,它不是。他们的行为也不同。除此之外。 ++ 是运算符而不是方法。
  • 您还建议ints 是不可变的,可能值得澄清该声明。
【解决方案3】:

我建议只返回结果而不是尝试更改不可变的int

  // int instead of void
  public static int SetBit(this int A, int k, bool set) { 
    return set ? (A | (1 << k)) : (A & (~(1 << k))); 
  }

所以你可以这样做

  int source = 12345;
  int result = source.SetBit(3, true);

【讨论】:

  • 我有多个答案在很短的时间内解释了最佳解决方案,我将这个作为有效答案,因为它非常清楚和重点,以及优化的单行句法。感谢所有花时间回答的人!
【解决方案4】:

我不得不检查一下,因为它看起来有点奇怪。果然——你不能用ref写扩展方法。

See here,有人试过这个。

【讨论】:

    【解决方案5】:

    您不能在扩展方法中混合使用 thisref。你有很多选择:

    1. 从扩展方法返回结果(我更喜欢这个选项):

      public static int SetBit(this int A, int k, bool set)
      {
          if (set) A |= 1 << k;
          else A &= ~(1 << k);
      
          return A;
      }
      

      使用:

      int i = 3;       
      i = i.SetBit(1, false); 
      
    2. 使用带有ref的方法:

      public static void SetBitRef(ref int A, int k, bool set)
      {
          if (set) A |= 1 << k;
          else A &= ~(1 << k);
      }
      

      使用:

          int i = 3;
          IntExtensions.SetBitRef(ref i, 1, false);
      
    3. 使用 IntWrapper 类代替 int:

          class IntWrapper
          {
              public IntWrapper(int intValue)
              {
                  Value = intValue;
              }
      
              public int Value { get; set; }
          }
      

      使用引用类型,您可以创建此扩展方法:

      public static void SetBit(this IntWrapper A, int k, bool set)
      {
          int intValue = A.Value;
      
          if (set) intValue |= 1 << k;
          else intValue &= ~(1 << k);
      
          A.Value = intValue;
      }
      

      使用:

      IntWrapper iw = new IntWrapper(3);
      iw.SetBit(1, false);
      

    【讨论】:

      猜你喜欢
      • 2014-08-08
      • 2021-08-15
      • 1970-01-01
      • 2015-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-14
      相关资源
      最近更新 更多