2016-12-19 48 views
3

通常建議在.NET編程中使用不可變結構,因爲使用可變結構會爲簡單錯誤設置一個結構。但是,當我嘗試通過實例化新結構來分配新值時,我在C++中得到C3892錯誤,但C#中的等效代碼沒有問題。這是一個問題,因爲這會阻止我初始化一個不可變結構數組。在C++/CLI中將新值分配給不可變值結構

這個問題很容易通過使用readonly屬性而不是字段來解決,但我想知道爲什麼我不能在C++中使用C++/CLI做同樣的事情。我做錯了什麼,或者這只是C++/CLI中的一個限制(或錯誤)?有什麼方法可以在C++/CLI中使用不可變結構數組,還是必須避免它們?

C++頭(名爲 「AnnoyingCppBug.h」):

using namespace System; 

namespace AnnoyingCppBug { 

    public value struct immutableType 
    { 
     const int Value; 

     immutableType(int value) 
      : Value(value) {} 
    }; 

    public value struct immutableWorkaround 
    { 
     property int Value 
     { 
      int get() { return _value; } 
     } 

     immutableWorkaround(int value) 
      : _value(value) {} 
    private: 
     int _value; 
    }; 

    public value struct mutableType 
    { 
     int Value; 

     mutableType(int value) 
      : Value(value) {} 
    }; 

    public value struct Class1 abstract sealed 
    { 
     static void Test(); 
    }; 
} 

C++源文件:

,做同樣的,但細建立
#include "stdafx.h" 

#include "AnnoyingCppBug.h" 

namespace AnnoyingCppBug { 
    void Class1::Test() 
    { 
     auto imm1 = immutableType(0); 
     auto imm2 = immutableWorkaround(0); 
     auto imm3 = mutableType(0); 

     imm1 = immutableType(1); // error C3892: 'arr1': you cannot assign to a variable that is const 
     imm2 = immutableWorkaround(1); 
     imm3 = mutableType(1); 

     // The reason this matters is because I need to initialize an array: 
     auto arr = gcnew array<immutableType>(1); 
     arr[0] = immutableType(0); // error C3892: 'arr1': you cannot assign to a variable that is const 
    } 
} 

C#代碼:

struct immutableType 
    { 
     public readonly int Value; 
     public immutableType(int value) 
     { 
      Value = value; 
     } 
    } 

    static void Test() 
    { 
     var imm = new immutableType(0); 
     imm = new immutableType(1); 
     var arr = new immutableType[1]; 
     arr[0] = new immutableType(1); 
    } 
+0

這不是一個bug,編譯器只是遵循C++規則的auto。使用auto你隱藏_issue_。編譯器可以推斷出該上下文中的第一個聲明是const(注意我寫了const,而不是不可變的),那麼它就是你得到的類型。另一方面在C#中const是一個完全不同的東西... –

+0

@AdrianoRepetti我仍然得到相同的錯誤,如果我明確宣佈一個非const類型的imm1聲明,並且該數組也沒有聲明爲一個常量數組在.NET中不存在const數組的類型) –

+1

'const'並不意味着你認爲它的作用,它是純粹的本地C++關鍵字。 CLR沒有任何支持,C++/CLI編譯器盡其所能地使它在行爲上類似,它在這裏。你正在尋找的是'initonly'關鍵字,它與C#中'readonly'關鍵字的確切等價物。 –

回答

3

答案由Hans帕桑特在評論上的問題提供:我錯誤地使用C++的唯一(不是C++/CLI)const關鍵字,如果它意味着同C#的關鍵字只讀。將只讀等效於C#關鍵字編譯成CLR的正確關鍵字是「initonly」。

const關鍵字將僅指示編譯器生成錯誤,但不會產生任何不同的CLR字節碼。一般來說,鑑於此啓示,我建議不要在託管C++代碼中使用const關鍵字。我也認爲C++/CLI編譯器應該生成一個警告,但也許有很好的理由它不會(畢竟編譯器不是老師)。

-1

我想你可能只是在你的數組創建中有一個錯字。它在immutableType之後缺少^。這個工作對我來說:

auto arr = gcnew array<immutableType^>(2); 
arr[0] = immutableType(1); 
arr[1] = immutableType(20);