[.net] String.Empty가 상수가 아닌 이유는 무엇입니까?

.Net에서 왜 String.Empty가 상수 대신 읽기 전용입니까? 그 결정의 근거가 무엇인지 아는 사람이 있는지 궁금합니다.



답변

그 이유 static readonly대신에 사용됩니다 const여기에 마이크로 소프트에 의해 지시 된 바와 같이, 관리되지 않는 코드를 사용하기 때문이다 공유 소스 공용 언어 인프라 2.0 릴리스 . 살펴볼 파일은 sscli20\clr\src\bcl\system\string.cs입니다.

Empty 상수는 빈 문자열 값을 보유합니다. 컴파일러가 이것을 리터럴로 표시하지 않도록 String 생성자를 호출해야합니다.

이것을 리터럴로 표시하면 네이티브에서 액세스 할 수있는 필드로 표시되지 않습니다.

CodeProject의이 편리한 기사 에서이 정보를 찾았습니다 .


답변

나는 여기에 많은 혼란과 나쁜 반응이 있다고 생각합니다.

우선, const필드는 static멤버입니다 ( 인스턴스 멤버가 아님) 아님)입니다.

섹션 10.4 C # 언어 사양의 상수를 확인하십시오.

상수는 정적 멤버로 간주되지만 상수 선언은 정적 수정자를 요구하거나 허용하지 않습니다.

만약 public const 회원은 정적, 하나는 상수는 새 개체를 만들 것이라고 생각하지 못했습니다.

이를 감안할 때 다음 코드 줄은 새 객체 생성과 관련하여 정확히 동일한 기능을 수행 합니다 .

public static readonly string Empty = "";
public const string Empty = "";

다음은 2의 차이점을 설명하는 Microsoft의 참고 사항입니다.

읽기 전용 키워드는 const 키워드와 다릅니다. const 필드는 필드 선언시에만 초기화 할 수 있습니다. 읽기 전용 필드는 선언 또는 생성자에서 초기화 될 수 있습니다. 따라서 읽기 전용 필드는 사용 된 생성자에 따라 다른 값을 가질 수 있습니다. 또한 const 필드는 컴파일 타임 상수이지만 읽기 전용 필드는 런타임 상수에 사용할 수 있습니다 …

그래서 여기서 유일하게 그럴듯한 대답은 Jeff Yates의 것입니다.


답변

String.Empty read only instead of a constant?

문자열을 일정하게 만들면 컴파일러는 실제로 문자열로 바뀝니다. 호출하는 모든 곳 바뀌고 코드를 같은 문자열로 채우고 코드가 실행될 때 다른 메모리에서 해당 문자열을 반복해서 읽어야합니다. 데이터.

문자열을 한곳에서만 읽은 채 그대로두면 String.Empty 프로그램은 같은 문자열을 한곳에 만 유지하고 읽거나 참조하여 데이터를 메모리에 최소로 유지합니다.

또한 String.Empty를 const로 사용하여 dll을 컴파일하고 어떤 이유로 String.Empty가 변경되면 컴파일 된 dll은 더 이상 동일하게 작동하지 않습니다. cost . 내부 코드에서 실제로 문자열의 사본을 유지하기 때문입니다. 모든 전화에.

예를 들어이 코드를 참조하십시오

public class OneName
{
    const string cConst = "constant string";
    static string cStatic = "static string";
    readonly string cReadOnly = "read only string";

    protected void Fun()
    {
        string cAddThemAll ;

        cAddThemAll = cConst;
        cAddThemAll = cStatic ;
        cAddThemAll = cReadOnly;
    }
}

컴파일러는 다음과 같이 올 것이다 :

public class OneName
{
    // note that the const exist also here !
    private const string cConst = "constant string";
    private readonly string cReadOnly;
    private static string cStatic;

    static OneName()
    {
        cStatic = "static string";
    }

    public OneName()
    {
        this.cReadOnly = "read only string";
    }

    protected void Fun()
    {
        string cAddThemAll ;

        // look here, will replace the const string everywhere is finds it.
        cAddThemAll = "constant string";
        cAddThemAll = cStatic;
        // but the read only will only get it from "one place".
        cAddThemAll = this.cReadOnly;

    }
}

그리고 어셈블리 호출

        cAddThemAll = cConst;
0000003e  mov         eax,dword ptr ds:[09379C0Ch]
00000044  mov         dword ptr [ebp-44h],eax
        cAddThemAll = cStatic ;
00000047  mov         eax,dword ptr ds:[094E8C44h]
0000004c  mov         dword ptr [ebp-44h],eax
        cAddThemAll = cReadOnly;
0000004f  mov         eax,dword ptr [ebp-3Ch]
00000052  mov         eax,dword ptr [eax+0000017Ch]
00000058  mov         dword ptr [ebp-44h],eax 

편집 : 오타 수정


답변

이 답변은 역사적 목적으로 존재합니다.

원래:

때문에 String클래스 상수가 될 수 없습니다.

확장 된 토론 :

이 답변을 심사하는 데 유용한 대화가 많이 생겼으며, 삭제하는 대신이 내용이 직접 재생산됩니다.

.NET에서 (Java와 달리) string과 String은 정확히 동일합니다. 그리고 네, .NET에서 문자열 리터럴 상수를 가질 수 있습니다 – DrJokepu Feb 3 ’09 at 16:57

당신은 클래스가 상수를 가질 수 없다고 말하는가? – StingyJack 2009 년 2 월 3 일 16:58

예, 개체는 읽기 전용을 사용해야합니다. 구조체 만 상수를 수행 할 수 있습니다. 나는 당신이 string대신 사용할 때 생각String컴파일러 하면 const가 읽기 전용으로 변경됩니다. C 프로그래머를 행복하게하는 것과 관련된 모든 것. – Garry Shutler 2009 년 2 월 3 일 16:59

tvanfosson은 조금 더 장황하게 설명했습니다. “Y를 포함하는 클래스이기 때문에 X는 상수가 될 수 없습니다”는 문맥이 너무 조금도 없었습니다.) – Leonidas

string.Empty는 String 클래스 자체가 아니라 String 클래스의 인스턴스, 즉 빈 문자열을 반환하는 정적 속성입니다. – tvanfosson 2009 년 2 월 3 일 17:01

Empty는 String 클래스의 읽기 전용 인스턴스입니다 (속성이 아님). – senfo 2 월 3 ’09 일 17:02

머리가 아프다. 나는 아직도 내가 옳다고 생각하지만 지금은 확실하지 않다. 오늘 밤 연구가 필요했습니다! – Garry Shutler 2009 년 2 월 3 일 17:07

빈 문자열은 문자열 클래스의 인스턴스입니다. Empty는 String 클래스의 정적 필드입니다 (속성이 아님, 정정되었습니다). 기본적으로 포인터와 그것이 가리키는 것의 차이점. 읽기 전용이 아닌 경우 Empty 필드가 참조하는 인스턴스를 변경할 수 있습니다. – tvanfosson 2009 년 2 월 3 일 17:07

개리, 당신은 어떤 연구를 할 필요가 없습니다. 생각 해봐 문자열은 클래스입니다. Empty는 String의 인스턴스입니다. – senfo 2 월 3 ’09 일 17:12

내가 얻지 못한 것이 있습니다 : 어떻게 지구상에서 String 클래스의 정적 생성자가 String 클래스의 인스턴스를 만들 수 있습니까? 일종의 “닭고기 또는 계란”시나리오가 아닌가? – DrJokepu 2012 년 2 월 3 일 17:12 5

이 대답은 System.String 이외의 거의 모든 클래스에 맞습니다. .NET은 문자열에 대해 많은 특수 성능을 수행하며 그중 하나는 문자열 상수를 가질 수 있다는 것입니다. 이 경우 Jeff Yates가 정답입니다. – Joel Mueller 2009 년 2 월 3 일 19:25

§7.18에서 설명한 것처럼 상수 표현식은 컴파일 타임에 완전히 평가할 수있는 표현식입니다. 문자열 이외의 참조 유형의 널이 아닌 값을 작성하는 유일한 방법은 새 연산자를 적용하는 것이며, 새 연산자는 상수 표현식에서 허용되지 않으므로 참조 유형의 상수에 가능한 유일한 값 문자열 이외의 null이 있습니다. 앞의 두 의견은 C # 언어 사양에서 직접 가져와 Joel Mueller가 언급 한 내용을 반복합니다. – senfo 2 월 4’09시 15:05 5


답변