2010-01-21 4 views
11

의 내부는 내가 선택 System.String의 내부 필드를보고 반사를 사용하고 내가 세 필드 발견이 어떻게 작동하는지선택 System.String

m_arrayLength 

m_stringLength 

m_firstChar 

가 이해가 안가.

m_arrayLength는 일부 배열의 길이입니다. 이 어레이는 어디에 있습니까? 그것은 분명히 문자열 클래스의 멤버 필드가 아닙니다.

m_stringLength가 적합합니다. 그것은 문자열의 길이입니다.

m_firstChar는 문자열의 첫 번째 문자입니다.

그럼 내 질문은 문자열의 나머지 문자는 어디입니까? 문자열 클래스에없는 경우 저장된 문자열의 내용은 어디에 있습니까?

답변

10

System.String 구현의 대부분은 네이티브 코드 (C/C++)이며 관리 코드 (C#)는 아닙니다. 만 도우미/편의 API가 일부는 C#으로 구현

[MethodImpl(MethodImplOptions.InternalCall)] 

: 당신은 디 컴파일 코드를 살펴 경우에 당신은 "흥미로운"또는 "핵심"방법의 대부분이이 속성에 장식되어 있음을 볼 수 있습니다 .

문자열의 문자는 어디에 저장되어 있습니까? 일급 비밀! CLR의 핵심 원시 코드 구현 내부 깊숙히 자리 잡고 있습니다.

2

나는 즉시 m_firstChar이 아니라고 생각할 것입니다. 첫 번째 문자가 아니라 첫 번째 문자를 가리키는 포인터입니다. 그것은 훨씬 더 의미가있을 것입니다. (비록 내가 소스에 관여하지 않기 때문에, 나는 확신 할 수 없습니다.)

blindingly fast s.substring(0,1) 작업을 원한다면 문자열의 첫 번째 문자를 저장하는 것은 거의 의미가 없습니다. :-) 문자 그 자체 (세 개의 필드가 암시하는)는 실제 개체와 별도로 할당됩니다. .

12

첫 번째 문자는 버퍼의 주먹 메모리에있는 주소에 (&m_firstChar을 통해) 액세스를 제공합니다. 길이는 얼마나 많은 문자가 string에 있는지 알려주므로 .Length을 효율적으로 만듭니다 (nul 문자를 찾는 것보다 낫습니다). 문자열은 크기가 커질 수 있습니다 (특히 StringBuilder 및 몇 가지 다른 시나리오로 만든 경우), 실제 버퍼가 실제로 문자열보다 긴 경우가 있습니다. 따라서 이것을 추적하는 것이 중요합니다. 예를 들어 StringBuilder는 실제로 은 버퍼 내에 문자열을 변형하므로 더 큰 버퍼를 만들기 전에 추가 할 수있는 양을 알아야합니다 (예 : AppendInPlace 참조). 문자열과 선택 System.String의 차이에

+0

@Marc에 대해 아무것도 없다, 나는 당신의 설명 (단지 첫 번째 비트가) 조금 혼란 생각합니다. 'm_firstChar'가'char' 인 경우, 그 주소는 문자열의 위치가 될 수 없습니다. 대신'char' 배열에있는 첫 번째 문자의 주소), 포인터의 주소를 알려주는'& m_firstChar'를 사용하는 것은 의미가 없습니다. 가능성이있는 형제들과 C#이 크게 다르지 않다면 - 나는 그것에 관해 많은 것을 알지 못합니다. – paxdiablo

+0

@paxdiablo 디 컴파일 된 코드를 보면 첫 번째 문자가 메모리 내 문자열의 실제 첫 번째 문자라는 것을 알 수 있습니다. 따라서 주소를 가져 와서 초기 메모리 주소를 인덱싱하면 나머지 문자가됩니다. – Eilon

+0

그래서 m_firstChar는 실제로 배열입니다 (C에서 포인터로 저하됩니다)? – paxdiablo

관련 문제