2016-08-16 66 views
4



我有,我想用這樣非常簡單的位運算符的方法:
C# - 引用「這INT」參數

myInt.SetBit(int k, bool set) 

,以便它改變了位索引「K」來值「設置」(0或1)我首先想到做這樣的:

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

但當然這只是改變變量「A」的內部值,而不是原來的變量,因爲整數ISN是一種參考類型。
我不能將'ref'和'this'一起使用,所以我不知道如何將它變成參考參數。
我已經有類似的方法爲Int數組,但是這些工作正常,因爲數組是一個引用類型。

我正在尋找一種方法來保持單個整數的這種方便的語法,如果有的話。

+1

將您的簽名從'void'更改爲'int'並返回新值。 – Igor

回答

1

我建議剛返回的結果,而不是試圖改變一成不變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); 
+0

我有很多答案可以在很短的時間內解釋最好的解決方案,我將這個答案作爲有效的答案,因爲它非常清晰並且重點突出,同時還提供了優化的單行語法。 感謝大家花時間回答! – grr

5

你不應該把它當作參考類型。

使您的方法返回修改的值並將其分配回您的變量。該方法將與不可變類型保持一致。考慮String.Replace的示例,它不會修改字符串,而是返回修改後的副本。

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

    return A; 
} 
+0

感謝您的快速回答! 雖然它將語法更改爲「myInt = myInt.SetBit(parameters)」,而不是簡單地使用「myInt.SetBit(parameters)」自身工作,但它具有很多意義。 我希望保持簡單的語法,但我想改變它可能是必要的,這聽起來確實是最好的解決方案。 – grr

0

我不得不檢查一下,因爲它看起來有點奇怪。果然 - 你不能使用ref寫一個擴展方法。

See here,別人已經試過這個。

4

某些類型(如int S)是不可改變的,也就是說,一旦他們被設置爲一個值,他們不能再被改變。您會注意到,在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); 
+0

*你會注意到,任何工作在一個int上的方法將返回一個新的int而不是改變給定值的值* - 除此之外,帶有'ref int'參數的方法除外...... – Rawling

+0

呃,不。那麼'x ++'怎麼樣? – DavidG

+0

x ++是x + = 1的語義糖,它是x = x + 1的語義糖。 – Glubus

0

不能混淆的擴展方法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:使用

    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; 
    } 
    

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

    與參考類型可以創建這個擴展方法

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