[c#] C #에서 const 매개 변수가 허용되지 않는 이유는 무엇입니까?

특히 C ++ 개발자에게는 이상하게 보입니다. C ++에서는 const메서드에서 상태가 변경되지 않도록 매개 변수를 다음과 같이 표시했습니다 . const refref로 전달하기 위해 전달하고 상태가 변경되지 않는지 확인하는 것과 같은 다른 C ++ 특정 이유도 있습니다. 그런데 왜 C #에서 메서드 매개 변수로 const로 표시 할 수 없습니까?

다음과 같이 메서드를 선언 할 수없는 이유는 무엇입니까?

    ....
    static void TestMethod1(const MyClass val)
    {}
    ....
    static void TestMethod2(const int val)
    {}
    ....



답변

다른 좋은 답변 외에도 C 스타일의 constness를 C #에 넣지 않는 또 다른 이유를 추가하겠습니다. 당신은 말했다 :

메서드에서 상태가 변경되지 않도록 매개 변수를 const로 표시합니다.

const가 실제로 그렇게했다면 그것은 좋을 것입니다. Const는 그렇게하지 않습니다. const는 거짓말입니다!

Const는 실제로 사용할 수 있다는 보장을 제공하지 않습니다. const 일을 취하는 메소드가 있다고 가정하십시오. 두 명의 코드 작성자가 있습니다. 호출자를 작성하는 사람수신자를 작성하는 사람 입니다. 피 호출자의 작성자는 메소드가 const를 취하도록 만들었습니다. 두 저자는 객체에 대해 무엇이 변하지 않는다고 가정 할 수 있습니까?

아무것도. 피 호출자는 const를 캐스트하고 객체를 변경할 수 있으므로 호출자는 const를 취하는 메서드를 호출하는 것이 실제로 변경되지 않는다는 보장 이 없습니다. 마찬가지로 피 호출자는 객체의 내용이 피 호출자의 작업 내내 변경되지 않을 것이라고 가정 할 수 없습니다. 피 호출자 는 const 객체의 비 const 별칭 에 대해 일부 mutating 메서드를 호출 할 수 있으며 이제 소위 const 객체가 변경되었습니다 .

C 스타일 const는 객체가 변경되지 않아 손상된다는 보장을 제공하지 않습니다. 이제 C는 이미 원할 경우 double을 int로 재 해석 할 수있는 약한 유형 시스템을 가지고 있으므로 const에 대해서도 약한 유형 시스템을 가지고 있다는 것은 놀라운 일이 아닙니다. 그러나 C #은 좋은 형식 시스템 을 갖도록 설계되었습니다. “이 변수에는 문자열이 포함되어 있습니다”라고 말하면 변수가 실제로 문자열 (또는 null)에 대한 참조를 포함하는 형식 시스템 입니다. 우리 는 타입 시스템이 거짓말이되는 것을 원하지 않기 때문에 C 스타일의 “const”수정자를 타입 시스템에 넣는 것을 절대 원하지 않습니다 . 코드에 대해 올바르게 추론 할 수 있도록 유형 시스템이 강력 하기를 바랍니다 .

Const in C는 지침입니다 . 그것은 기본적으로 “이것을 변형 시키려하지 않기 위해 나를 믿을 수있다”는 의미입니다. 그것은 타입 시스템 에 있어서는 안됩니다 . 에서 물건 타입 시스템은 해야 사실 당신이하지에 대해 추론 할 수있는 개체에 대한 가이드 라인 의 사용합니다.

자, 오해하지 마십시오. C의 const가 깊이 깨 졌다고해서 전체 개념이 쓸모 없다는 의미는 아닙니다. 내가보고 싶은 것은 C #에서 실제로 정확 하고 유용한 형태의 “const”주석입니다. 이는 인간과 컴파일러 모두가 코드를 이해하는 데 사용할 수 있고 런타임이 자동 병렬화와 같은 작업을 수행하는 데 사용할 수있는 주석입니다. 기타 고급 최적화.

예를 들어, 한 덩어리의 코드 주위에 “상자를 그리고” 컴파일러가 확인할 수있는 방식으로 “이 코드 덩어리가이 클래스의 어떤 필드에도 변형을 수행하지 않는다는 것을 보장 합니다 “라고 말할 수 있다고 상상해보십시오 . 또는 “이 순수한 방법은 개체의 내부 상태를 변경하지만 상자 외부에서 관찰 할 수있는 방식은 변경하지 않습니다.”라는 상자를 그립니다. 이러한 객체는 자동으로 안전하게 다중 스레드 될 수 없지만 자동으로 메모 될 수 있습니다 . 풍부한 최적화와 더 깊은 이해를 가능하게하는 코드에 추가 할 수있는 모든 종류의 흥미로운 주석이 있습니다. 약한 C 스타일의 const 주석보다 더 잘할 수 있습니다.

그러나 나는 이것이 단지 추측이라고 강조한다 . 우리는 이런 종류의 기능을 C #의 가상 미래 버전에 넣을 확고한 계획이 없습니다. 이것은 제가보고 싶은 것입니다. 다가오는 멀티 코어 컴퓨팅에 대한 강조가 필요할 수도 있지만, 어떤 식 으로든 C #의 특정 기능 또는 미래 방향에 대한 예측이나 보장으로 해석되어서는 안됩니다.

이제 원하는 것이 “이 매개 변수의 값은 메소드 전체에서 변경되지 않습니다”라는 매개 변수 인 로컬 변수에 대한 주석뿐이라면, 확실히 쉽게 수행 할 수 있습니다. 한 번 초기화되는 “읽기 전용”지역 및 매개 변수와 메서드에서 변경되는 컴파일 타임 오류를 지원할 수 있습니다. “using”문에 의해 선언 된 변수는 이미 그러한 지역입니다. 모든 지역 및 매개 변수에 선택적 주석을 추가하여 “사용”변수처럼 작동하도록 만들 수 있습니다. 우선 순위가 매우 높은 기능이 아니므로 구현 된 적이 없습니다.


답변

C #에 const 정확성 이없는 이유 중 하나는 런타임 수준에 존재하지 않기 때문입니다. C # 1.0은 런타임의 일부가 아닌 한 기능이 없었 음을 기억하십시오.

CLR에 const 정확성 개념이없는 몇 가지 이유는 다음과 같습니다.

  1. 이는 런타임을 복잡하게합니다. 게다가, JVM도 가지고 있지 않았고, CLR은 기본적으로 C ++와 같은 런타임이 아닌 JVM과 같은 런타임을 만드는 프로젝트로 시작되었습니다.
  2. 런타임 수준에 const 정확성이있는 경우 BCL에 const 정확성이 있어야합니다. 그렇지 않으면 .NET Framework에 관한 한 기능이 거의 의미가 없습니다.
  3. 그러나 BCL에 const 정확성이 필요한 경우 CLR 위에있는 모든 언어는 const 정확성 (VB, JavaScript, Python, Ruby, F # 등)을 지원해야합니다 . 그런 일은 일어나지 않을 것입니다.

Const 정확성은 거의 C ++에만있는 언어 기능입니다. 따라서 CLR이 확인 된 예외 (Java 언어 전용 기능)를 필요로하지 않는 이유와 동일한 주장으로 귀결됩니다.

또한 이전 버전과의 호환성을 깨지 않고 관리 환경에서 이러한 기본적인 유형 시스템 기능을 도입 할 수 없다고 생각합니다. 따라서 C # 세계에 들어온 const 정확성에 의존하지 마십시오.


답변

C #이 const가 맞지 않는 데에는 두 가지 이유가 있다고 생각합니다.

첫 번째는 이해 가능성 입니다. const 정확성을 이해하는 C ++ 프로그래머는 거의 없습니다. 의 간단한 예 const int arg는 귀엽지 만 char * const * const arg상수가 아닌 문자에 대한 상수 포인터에 대한 상수 포인터 도 보았습니다 . 함수 포인터에 대한 상수 정확성은 완전히 새로운 수준의 난독 화입니다.

두 번째는 클래스 인수가 값으로 전달되는 참조이기 때문입니다. 이것은 명백하게 명확한 구문 없이 처리 할 두 가지 수준의 constness가 이미 있음을 의미 합니다 . 비슷한 걸림돌은 컬렉션 (및 컬렉션 컬렉션 등)입니다.

상수 정확성은 C ++ 유형 시스템의 중요한 부분입니다. 이론적으로는 컴파일시에만 확인되는 것으로 C #에 추가 될 수 있습니다 (CLR에 추가 할 필요가 없으며 const 멤버 메서드 개념이 포함되지 않는 한 BCL에 영향을주지 않음). .

그러나 나는 이것이 가능성이 없다고 생각합니다. 두 번째 이유 (구문)는 해결하기가 매우 어려울 것이며, 이는 첫 번째 이유 (이해성)를 훨씬 더 문제로 만들 것입니다.


답변

constC #에서 “컴파일 시간 상수”를 의미하며 C ++에서와 같이 “읽기 전용이 아니라 다른 코드에 의해 변경 가능”을 의미합니다. constC #에서 C ++의 대략적인 유사점은 readonly이지만 필드에만 적용 할 수 있습니다. 그 외에도 C #에서 const 정확성에 대한 C ++와 같은 개념은 전혀 없습니다.

많은 잠재적 인 이유가 있기 때문에 그 이유를 확실히 말하기는 어렵지만, 제 생각에는 언어를 가장 먼저 단순하게 유지하고이 두 번째 구현의 불확실한 이점을 유지하고자 할 것입니다.


답변

이는 C # 7.2 (2017 년 12 월 Visual Studio 2017 15.5 포함)부터 가능합니다.

Structs 및 기본 유형 에만 해당됩니다! , 클래스 구성원이 아닙니다.

in참조에 의한 입력으로 인수를 보내 려면를 사용해야합니다 . 보다:

참조 :
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/in-parameter-modifier

예를 들어 :

....
static void TestMethod1(in MyStruct val)
{
    val = new MyStruct;  // Error CS8331 Cannot assign to variable 'in MyStruct' because it is a readonly variable
    val.member = 0;  // Error CS8332 Cannot assign to a member of variable 'MyStruct' because it is a readonly variable
}
....
static void TestMethod2(in int val)
{
    val = 0;  // Error CS8331 Cannot assign to variable 'in int' because it is a readonly variable
}
....


답변