C #에서 읽기 전용 지역 변수를 허용하지 않는 이유는 무엇입니까?


115

이에 대해 동료와 우호적 인 토론을합니다. 우리는 이것에 대해 약간의 생각을 가지고 있지만 SO 군중이 이것에 대해 어떻게 생각하는지 궁금하십니까?


4
@ColonelPanic C 및 C ++에는 런타임 계산 값으로 초기화 할 수있는 const 로컬 변수가 있습니다.
Crashworks

1
JavaScript 2015 (ES6)에는 const 유형이 있습니다. 예 : {const myList = [1,2,3]; }. 이 구조를 사용하는 것은 매우 좋은 프로그래밍 관행입니다. 더 많은 정보 : developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
andrew.fox

1
관심있는 사람들 을 위해이 기능에 대한 UserVoice 제안이 있습니다 . 현재 87 표에 불과하므로 로컬 읽기 전용 변수를보고 싶다면 부디 부디!
Ian Kemp

1
언어 문제가 아닙니다. 가장 높은 등급의 C # 전문가를 포함하여 C # 커뮤니티의 대다수가 const 정확성 및 이와 관련된 모든 것에 대해 신경 쓰지 않는 것이 문제입니다. 저항은 무의미하다.
패트릭 Fromberg

1
2017 업데이트 : C # 언어 디자인 리포지토리에서 논의중인 기능 요청에 투표하세요! github.com/dotnet/csharplang/issues/188
대령 패닉

답변:


15

한 가지 이유는 읽기 전용 로컬에 대한 CLR 지원이 없기 때문입니다. 읽기 전용은 CLR / CLI initonly opcode로 변환됩니다. 이 플래그는 필드에만 적용 할 수 있으며 로컬에는 의미가 없습니다. 실제로 로컬에 적용하면 확인할 수없는 코드가 생성 될 수 있습니다.

이것은 C #이 이것을 할 수 없다는 것을 의미하지 않습니다. 그러나 동일한 언어 구조에 두 가지 다른 의미를 부여합니다. 로컬 버전에는 CLR에 해당하는 매핑이 없습니다.


57
로컬 변수는 다른 어셈블리에 노출되지 않기 때문에 기능에 대한 CLI 지원과는 실제로 관련이 없습니다. readonly필드 의 키워드는 그 효과 다른 어셈블리에 표시 되므로 CLI에서 지원해야합니다 . 그것이 의미하는 것은 변수가 컴파일 타임에 메서드에 하나의 할당 만 있다는 것입니다.
Sam Harwell

16
나는 당신이 왜 CLR이 합리적 근거를 제공하지 않고 이것을 지원하지 않는지에 대한 질문을 옮겼다 고 생각합니다. const 로컬을 허용하므로 읽기 전용 로컬도 예상하는 것이 합리적입니다.
Chad Schouggins

9
이것의 예는 using 문에 정의 된 변수입니다. 로컬 ... 및 읽기 전용입니다 (할당하려고하면 C #에서 오류가 추가됨).
Softlion 2013

7
-1 C ++에는 기계어 코드 지원이 없습니다 const(C ++에서는 두 역할을 모두 수행 할 수 있지만 C # readonly보다 C #과 비슷 const합니다). 그러나 C ++는 const지역 자동 변수를 지원 합니다. 따라서 readonly지역 변수에 대한 C #에 대한 CLR 지원의 부족 은 관련이 없습니다.
건배와 hth. - 알프

5
1. 이것은 C ++ 에서처럼 쉽게 컴파일러 기능이 될 수 있습니다. CLR 지원은 전혀 관련이 없습니다. 기계 조립도 지원하지 않습니다. 2. (그것이) 검증 할 수없는 코드를 생성 할 가능성이 있습니다 .-방법은 모르겠지만 아마도 제가 잘못 알고있을 것입니다. 3. 동일한 언어 구조에 대한 두 가지 다른 의미를 줄 것이다 - 나는 때문에, 사람이 문제로 볼 것이다 의심 using하고 out정확하고 있음을하며 세계는 붕괴하지 않았다.
Lou

66

나는 C # 아키텍트의 일부에 대한 잘못된 판단이라고 생각합니다. 지역 변수에 대한 readonly 한정자는 프로그램 정확성을 유지하는 데 도움이되고 (어설 션과 마찬가지로) 컴파일러가 코드를 최적화하는 데 도움이 될 수 있습니다 (적어도 다른 언어의 경우). 현재 C #에서 허용되지 않는다는 사실은 C #의 "기능"중 일부가 제작자의 개인 코딩 스타일을 적용한 것일 뿐이라는 또 다른 주장입니다.


11
나는 "프로그래머를 자신으로부터 구하라"부분에 동의하지만 컴파일러가 코드를 최적화하도록 돕는 것에 관해서는 컴파일러가 메소드 과정에서 변수가 변경되는지 여부를 매우 잘 알아 내고 그에 따라 최적화 할 수 있다는 입장을 유지합니다. 어느 쪽이든. 옵티마이 저가 그 목적을 위해 인식하는 것 앞에 '읽기 전용'플래그를 두는 것은 실제로 이익이되지는 않지만 잠재적으로 오해를 불러 일으킬 수 있습니다.
Cornelius

1
@Cornelius 어떤 경우에는 컴파일러가 키워드 / 수정 자에 관계없이 최적화 기회를 파악하기 위해 데이터 흐름 다이어그램을 사용한다는 의견이 있다는 데 동의합니다. 그러나 프로그래머가 잘못 작성하거나 불필요하게 최적화되지 않은 코드를 작성하지 못하게하면 컴파일러에 대한 최적화 기회가 열릴 수 있습니다.
shuva

어쨌든 현대 컴파일러는 정적 단일 할당을 수행하지 않습니까? 어떤 경우에는 최적화와 관련하여 문제가 있습니다 (하지만 컴파일러가 SSA를 지원하는 경우 한 번 할당 지역 변수를 구현하는 것도 사소한 일임을 의미합니다).
다이

33

Jared의 대답을 처리하면 아마도 컴파일 타임 기능이어야 할 것입니다. 컴파일러는 초기 선언 (할당을 포함해야 함) 후에 변수에 쓰는 것을 금지합니다.

이것에서 가치를 볼 수 있습니까? 잠재적으로-솔직히 많이는 아닙니다. 변수가 메서드의 다른 위치에 할당 될지 여부를 쉽게 알 수 없다면 메서드가 너무 깁니다.

무엇의 가치를 들면, 자바합니다 (사용하여이 기능이 final수정을) 내가 한 매우 드물게 그것 경우 이외의 사용 본적 변수가 익명의 내부 클래스에 의해 포착 할 수 있도록 사용하는 - 그것은 어디에 이다 사용하면 유용한 정보가 아니라 어수선한 느낌을줍니다.


75
변수가 시각컴파일러에 의해 메서드에서 수정되는지 여부를 보는 것에는 차이가 있습니다 . 메서드를 작성하고, 변수를 수정하지 않겠다는 의도를 밝히고, 실수로 수행했을 때 컴파일러가 알려주도록하는 것에 대한 이의가 없습니다 (아마도 한 달 후 오타로 인해)!
A. Rex

50
반면에 F #에서는 모든 변수가 기본적으로 읽기 전용이므로 변경할 수 있도록하려면 'mutable'키워드를 사용해야합니다. F #은 .NET 언어이므로 설명하는 컴파일 시간 검사를 수행한다고 생각합니다.
Joel Mueller

2
@ A.Rex : 문제는 실제로 컴파일러가 검사를 수행하도록하는 이점이 코드를 읽을 때 추가 "보풀"이 될 가치가 있는지 여부입니다.
Jon Skeet

3
FWIW, Scala 는 및 키워드를 사용하여 지역 readonly/ final값을 변수와 구별 합니다. Scala 코드에서 local 은 매우 자주 사용 됩니다 (실제로 local s 보다 선호 됨 ). 수정자가 Java에서 더 자주 사용되지 않는 주된 이유 는 a) 혼란스럽고 b) 게으름 때문이라고 생각합니다. valvarvalvarfinal
Aaron Novstrup 2014-06-20

4
클로저에 사용되지 않는 지역 변수의 readonly경우 지나치게 중요하지 않습니다. 반면에 클로저에 사용되는 지역 변수의 readonly경우 많은 경우 컴파일러가 더 효율적인 코드를 생성 할 수 있습니다. 현재, 클로저가 포함 된 블록에 실행이 시작되면 컴파일러는 클로저를 사용하는 코드가 실행되지 않더라도 닫힌 변수에 대한 새 힙 객체를 만들어야합니다 . 변수가 읽기 전용이면 클로저 외부의 코드는 일반 변수를 사용할 수 있습니다. 클로저를 위해 델리게이트가 생성 된 경우에만 ...
supercat 2015-03-04

30

제안 읽기 전용 지역 및 매개 변수에 대한은 C # 7 디자인 팀에서 간략하게 논의했습니다. 에서 2015년 1월 21일에 대한 C # 디자인 회의 노트 :

매개 변수와 로컬은 람다로 캡처하여 동시에 액세스 할 수 있지만 공유 상호 상태 문제로부터 보호 할 수있는 방법은 없습니다. 읽기 전용 일 수 없습니다.

일반적으로 대부분의 매개 변수와 많은 로컬은 초기 값을 얻은 후에는 할당되지 않습니다. 그들에게 읽기 전용을 허용하면 그 의도를 명확하게 표현할 수 있습니다.

한 가지 문제는이 기능이 "매력적인 골칫거리"일 수 있다는 것입니다. "올바른 일"은 거의 항상 매개 변수와 지역을 읽기 전용으로 만드는 것이지만 그렇게하려면 코드가 상당히 복잡해집니다.

이를 부분적으로 완화하는 아이디어는 지역 변수의 readonly var 조합을 val 또는 이와 유사한 짧은 값으로 축소하는 것입니다. 더 일반적으로 우리는 읽기 전용을 표현하기 위해 설정된 읽기 전용보다 짧은 키워드를 생각할 수 있습니다.

토론은 C # 언어 디자인 리포지토리에서 계속됩니다. 지지를 보여주기 위해 투표하십시오. https://github.com/dotnet/csharplang/issues/188


읽기 전용을 기본값으로 설정할 수도 있습니다 (옵션이나 키워드 등을 통해). 대부분의 변수와 매개 변수는 읽기 전용이어야하며 몇 개만 쓸 수 있습니다. 쓰기 가능한 숫자를 최소화하는 것은 일반적으로 좋은 일입니다.
Dave Cousineau

12

C # 언어 디자이너의 감독입니다. F #에는 val 키워드가 있으며 CLR을 기반으로합니다. C #이 동일한 언어 기능을 가질 수없는 이유는 없습니다.


7

나는 그 동료 였고 친절하지 않았습니다! (농담)

짧은 메서드를 작성하는 것이 더 낫기 때문에 기능을 제거하지 않을 것입니다. 스레드는 어렵 기 때문에 사용하지 말아야한다고 말하는 것과 비슷합니다. 칼을 주시고 자상하지 않는 책임을지게 해주세요.

개인적으로 "inv"(invarient) 또는 "rvar"와 같은 또 다른 "var"유형의 키워드를 사용하여 혼란을 피했습니다. 나는 늦게 F #을 연구하고 있으며 불변하는 것이 매력적이라는 것을 알았습니다.

Java가 이것을 가지고 있다는 것을 결코 알지 못했습니다.


5

지역 const 변수 와 같은 방식으로 지역 읽기 전용 변수를 원합니다 . 그러나 다른 주제보다 우선 순위가 낮습니다. 아마도 그것의 우선 순위 는 C # 디자이너 가이 기능을 구현 하지 않는 (아직!) 동일한 이유 일 것입니다 . 그러나 향후 버전에서 로컬 읽기 전용 변수를 지원하는 것은 쉽고 (그리고 이전 버전과도 호환) 가능해야합니다.


2

읽기 전용은 인스턴스 변수를 설정할 수있는 유일한 위치가 생성자에 있음을 의미합니다. 변수를 로컬로 선언 할 때 인스턴스가 없으며 (범위 내에 있음) 생성자가 건드릴 수 없습니다.


6
이것이 C #에서 '읽기 전용'의 현재 의미이지만 질문이 아닙니다. '읽기 전용'은 지역 변수에 직관적으로 적용 할 수있는 영어 의미를 가지고 있습니다. 초기화 된 후에는 쓸 수 없습니다. 그것은 인스턴스 변수에 적용될 때의 의미와 매우 비슷해 보입니다. 그런데 왜 (정의에서와 같이) 지역 변수에 적용 할 수 없습니까?
Spike0xff

0

나는 이것이 당신의 질문에 대한 이유에 대한 답이 아닙니다. 어쨌든이 질문을 읽는 사람들은 그럼에도 불구하고 아래 코드를 고맙게 생각할 것입니다.

한 번만 설정해야하는 로컬 변수를 재정의 할 때 자신의 발에 자신을 쏘는 데 정말로 관심이 있고 더 전역 적으로 액세스 가능한 변수로 만들고 싶지 않은 경우 다음과 같이 할 수 있습니다.

    public class ReadOnly<T>
    {
        public T Value { get; private set; }

        public ReadOnly(T pValue)
        {
            Value = pValue;
        }

        public static bool operator ==(ReadOnly<T> pReadOnlyT, T pT)
        {
            if (object.ReferenceEquals(pReadOnlyT, null))
            {
                return object.ReferenceEquals(pT, null);
            }
            return (pReadOnlyT.Value.Equals(pT));
        }

        public static bool operator !=(ReadOnly<T> pReadOnlyT, T pT)
        {
            return !(pReadOnlyT == pT);
        }
    }

사용 예 :

        var rInt = new ReadOnly<int>(5);
        if (rInt == 5)
        {
            //Int is 5 indeed
        }
        var copyValueOfInt = rInt.Value;
        //rInt.Value = 6; //Doesn't compile, setter is private

코드만큼 rvar rInt = 5적지 는 않지만 작동합니다.


여기서는 도움이되지 않습니다. 변수 'var'의이 문제는 다음과 같습니다. {var five = 5 five = 6; Assert.That (five == 5)}
Murray

0

C # 대화 형 컴파일러를 사용하는 경우 C #에서 읽기 전용 지역 변수를 선언 할 수 있습니다 csi.

>"C:\Program Files (x86)\MSBuild\14.0\Bin\csi.exe"
Microsoft (R) Visual C# Interactive Compiler version 1.3.1.60616
Copyright (C) Microsoft Corporation. All rights reserved.

Type "#help" for more information.
> readonly var message = "hello";
> message = "goodbye";
(1,1): error CS0191: A readonly field cannot be assigned to (except in a constructor or a variable initializer)

.csx스크립트 형식으로 읽기 전용 지역 변수를 선언 할 수도 있습니다 .


5
오류 메시지에 따라 message여기서는 변수가 아니며 필드로 컴파일됩니다. 대화 형 C #에서도 구별이 명확하게 존재하기 때문에 이것은 간단하지 않습니다.int x; Console.WriteLine(x) 합법적 인 대화 형 C # ( x필드이고 암시 적으로 초기화 void foo() { int x; Console.WriteLine(x); }되었기 때문 )이지만 그렇지 않습니다 ( x변수이고 할당되기 전에 사용되기 때문입니다). 또한 이것이 실제로 지역 변수가 아닌 필드 Expression<Func<int>> y = x; ((MemberExpression) y.Body).Member.MemberType임을 나타냅니다 x.
Jeroen Mostert 2016

0

C #에는 약간 다른 구문이지만 이미 읽기 전용 var가 있습니다.

다음 줄을 고려하십시오.

var mutable = myImmutableCalculationMethod();
readonly var immutable = mutable; // not allowed in C# 8 and prior versions
return immutable;

비교 :

var mutable = myImmutableCalculationMethod();
string immutable() => mutable; // allowed in C# 7
return immutable();

첫 번째 해결책은 작성해야 할 코드가 적을 수 있습니다. 그러나 두 번째 스 니펫은 변수를 참조 할 때 읽기 전용을 명시 적으로 만듭니다.


그것은 "읽기 전용"이 아닙니다. 이것은 캡처 된 변수를 반환하는 로컬 함수입니다. 코드 액세스 관점에서 기본 변수를 읽기 전용으로 만들지 않는 불필요한 오버 헤드와 추악한 구문이 너무 많습니다. 또한 "변경 가능"은 일반적으로 지역 변수가 아닌 객체에 적용됩니다 readonly var im = new List<string>(); im.Add("read-only variable, mutable object!");.
user2864740

-2

사용하다 const읽기 전용 변수를 만들려면 키워드를 하십시오.

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

public class SealedTest
{
    static void Main()
    {
        const int c = 707;
        Console.WriteLine("My local constant = {0}", c);
    }
}

1
우리는 const변수가 초기화 동안에 만 할당 될 수 있는 JavaScript 스타일에 관심 const이 있습니다. 컴파일 타임 표현식 만 사용할 수있는 csharp 스타일 이 아닙니다. 예를 들어, 당신은 할 수 const object c = new object();있지만, readonly지역은 당신이 할 수있는 것입니다.
binki

-5

읽기 전용 변수가있는 함수는 절대 호출되지 않을 수 있기 때문이라고 생각합니다. 아마 범위를 벗어난 것이있을 수 있으며 언제 필요합니까?

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.