답변:
명백한 차이를 제외하고
const
VS readonly
값을 정의 할 때 값을 선언 해야하는 것은 동적으로 계산 될 수 있지만 생성자가 종료되기 전에 할당되어야합니다.static
있습니다. ClassName.ConstantName
표기법을 사용 하여 액세스합니다.미묘한 차이가 있습니다. 에 정의 된 클래스를 고려하십시오AssemblyA
.
public class Const_V_Readonly
{
public const int I_CONST_VALUE = 2;
public readonly int I_RO_VALUE;
public Const_V_Readonly()
{
I_RO_VALUE = 3;
}
}
AssemblyB
참조 AssemblyA
코드에서 이러한 값을 하고 사용합니다. 이것이 컴파일되면
const
값 의 경우 찾기 대치와 같으며 값 2는 ' AssemblyB
IL에 '구워집니다 ' . 이는 내일이면 I_CONST_VALUE
향후 20으로 업데이트 될 것임을 의미합니다 .AssemblyB
내가 다시 컴파일 할 때까지 여전히 2가있을 것 입니다.readonly
값 의 경우 ref
메모리 위치 와 같습니다 . 이 값은 AssemblyB
IL에 구워지지 않습니다 . 즉, 메모리 위치가 업데이트 AssemblyB
되면 재 컴파일하지 않고 새 값을 가져옵니다. 따라서 I_RO_VALUE
30으로 업데이트 되면 빌드 만하면 AssemblyA
됩니다. 모든 클라이언트를 다시 컴파일 할 필요는 없습니다.따라서 상수 값이 변경되지 않을 것이라고 확신한다면 const
.
public const int CM_IN_A_METER = 100;
그러나 변경 될 수있는 상수 (예 : 정밀도)가 있거나 의심스러운 경우을 사용하십시오 readonly
.
public readonly float PI = 3.14;
업데이트 : Aku는 먼저 이것을 지적한 coz를 언급해야합니다. 또한 이것을 배운 곳에 꽂아야합니다. 효과적인 C #-Bill Wagner
static
점은 가장 중요하고 유용한 점을 것 같다 -consts are implicitly static
readonly
변수는 생성자 외부에서 변경할 수 있습니다 (반사). 생성자 외부에서 var를 수정하는 것을 방해하는 것은 컴파일러 일뿐입니다.
readonly
변수는 생성자가 리플렉션을 통해 완료된 후에는 변경할 수 없습니다. 런타임은 이것을 강제하지 않습니다. 런타임은 변경하지 않는 것이 시행하지 않는 일 string.Empty
에 "Hello, world!"
,하지만, 난 여전히이하게 주장하지 않을 string.Empty
수정, 또는 그 코드가 가정해서는 안 string.Empty
항상 길이가 0 인 문자열이 될 것입니다.
추가하기 위해 참조 유형의 ReadOnly는 값이 아닌 참조 만 읽기 전용으로 만듭니다. 예를 들면 다음과 같습니다.
public class Const_V_Readonly
{
public const int I_CONST_VALUE = 2;
public readonly char[] I_RO_VALUE = new Char[]{'a', 'b', 'c'};
public UpdateReadonly()
{
I_RO_VALUE[0] = 'V'; //perfectly legal and will update the value
I_RO_VALUE = new char[]{'V'}; //will cause compiler error
}
}
string
상수로 사용할 수있는 것 이외의 다른 참조 유형이 있습니까?
const
string 이외의 참조 유형을 가질 수 있지만 상수는 값만 가질 수 있습니다 null
.
이것은 그것을 설명합니다 . 요약 : const는 선언시 초기화되어야하며 읽기 전용은 생성자에서 초기화 될 수 있으므로 사용 된 생성자에 따라 다른 값을 가질 수 있습니다.
편집 : 미묘한 차이점은 위의 Gishu의 gotcha를 참조하십시오.
읽기 전용의 작은 문제가 있습니다. 생성자 내에서 읽기 전용 필드를 여러 번 설정할 수 있습니다. 값이 두 개의 서로 다른 체인 생성자에 설정되어 있어도 여전히 허용됩니다.
public class Sample {
private readonly string ro;
public Sample() {
ro = "set";
}
public Sample(string value) : this() {
ro = value; // this works even though it was set in the no-arg ctor
}
}
상수 멤버는 컴파일 타임에 정의되며 런타임시 변경할 수 없습니다. 상수는 const
키워드를 사용하여 필드로 선언되며 선언 된대로 초기화해야합니다.
public class MyClass
{
public const double PI1 = 3.14159;
}
readonly
부재는 불변 값을 나타내는 것을 일정한 같다. 차이점은 readonly
런타임시 생성자에서 멤버를 초기화 할 수 있으며 선언 된대로 초기화 할 수 있다는 것입니다.
public class MyClass1
{
public readonly double PI2 = 3.14159;
//or
public readonly double PI3;
public MyClass2()
{
PI3 = 3.14159;
}
}
const
static
(내재적으로 정적 임).읽기 전용
static const int i = 0;
const
메소드 내에서 선언을 할 수 없는지 설명 할 수 있습니까 ?
const는 컴파일 타임 상수이지만 읽기 전용은 런타임에 값을 계산하고 생성자 또는 필드 이니셜 라이저에서 설정할 수 있습니다. 따라서 'const'는 항상 일정하지만 'readonly'는 일단 할당되면 읽기 전용입니다.
C # 팀의 Eric Lippert 는 다양한 유형의 불변성에 대한 자세한 정보를 제공합니다.
다음 은 const가 버전 안전하지 않거나 참조 유형과 관련이없는 방법을 보여주는 다른 링크 입니다.
요약 :
읽기 전용 : 런타임시 Ctor를 통해 값을 변경할 수 있습니다. 그러나 멤버 함수를 통하지 않음
상수 : 적분 정적. 어디에서나 값을 변경할 수 없습니다 (Ctor, Function, 런타임 등)
또 다른 문제 : 리플렉션을 통해 "독의"코드로 읽기 전용 값을 변경할 수 있습니다.
var fi = this.GetType()
.BaseType
.GetField("_someField",
BindingFlags.Instance | BindingFlags.NonPublic);
fi.SetValue(this, 1);
사무실의 팀원 중 한 명이 const, static 및 readonly 사용시기에 대한 다음 지침을 제공했습니다.
마지막 메모 : const 필드는 정적이지만 그 반대는 아닙니다.
둘 다 일정하지만 컴파일 타임에도 const를 사용할 수 있습니다. 이는 차이점의 한 측면은 const 변수를 속성 생성자에 대한 입력으로 사용할 수 있지만 읽기 전용 변수는 사용할 수 없다는 것입니다.
예:
public static class Text {
public const string ConstDescription = "This can be used.";
public readonly static string ReadonlyDescription = "Cannot be used.";
}
public class Foo
{
[Description(Text.ConstDescription)]
public int BarThatBuilds {
{ get; set; }
}
[Description(Text.ReadOnlyDescription)]
public int BarThatDoesNotBuild {
{ get; set; }
}
}
const로 표시된 변수는 강력한 형식의 #define 매크로에 지나지 않으며 컴파일시 const 변수 참조는 인라인 리터럴 값으로 대체됩니다. 결과적으로 특정 내장 기본 값 유형 만이 방식으로 사용될 수 있습니다. 읽기 전용으로 표시된 변수는 생성자에서 런타임에 설정할 수 있으며 해당 읽기 전용은 런타임 중에도 적용됩니다. 이와 관련된 약간의 성능 비용이 있지만 모든 유형 (참조 유형 포함)과 함께 읽기 전용을 사용할 수 있음을 의미합니다.
또한 const 변수는 본질적으로 정적 인 반면 읽기 전용 변수는 원하는 경우 인스턴스마다 다를 수 있습니다.
또 다른 문제가 있습니다.
const는 실제로 기본 데이터 형식에서만 작동하므로 클래스로 작업하려는 경우 ReadOnly를 사용하도록 "강제로"느껴질 수 있습니다. 그러나 함정에주의하십시오! ReadOnly는 객체를 다른 객체로 교체 할 수 없음을 의미합니다 (다른 객체를 참조하도록 할 수는 없음). 그러나 객체를 참조하는 모든 프로세스는 내부 의 값을 자유롭게 수정할 수 있습니다. 의 !
따라서 ReadOnly가 사용자가 내용을 변경할 수 없음을 암시한다고 혼동하지 마십시오. C #에는 클래스의 인스턴스화가 내부 값이 변경되지 않도록하는 간단한 구문이 없습니다 (내가 아는 한).
C # .Net의 const 필드와 readonly 필드에는 눈에 띄는 차이가 있습니다.
const는 기본적으로 정적이며 상수 값으로 초기화해야하며 나중에 수정할 수 없습니다. 생성자에서도 값을 변경할 수 없습니다. 모든 데이터 유형에 사용할 수는 없습니다. 예를 들어, DateTime. DateTime 데이터 유형과 함께 사용할 수 없습니다.
public const DateTime dt = DateTime.Today; //throws compilation error
public const string Name = string.Empty; //throws compilation error
public readonly string Name = string.Empty; //No error, legal
읽기 전용은 정적으로 선언 될 수 있지만 필수는 아닙니다. 선언 할 때 초기화 할 필요가 없습니다. 생성자를 사용하여 값을 할당하거나 변경할 수 있습니다. 따라서 인스턴스 클래스 멤버로 사용될 때 이점을 제공합니다. 두 개의 다른 인스턴스화는 다른 값의 읽기 전용 필드를 가질 수 있습니다. 예를 들어-
class A
{
public readonly int Id;
public A(int i)
{
Id = i;
}
}
그런 다음 다음과 같이 즉시 특정 값으로 읽기 전용 필드를 초기화 할 수 있습니다.
A objOne = new A(5);
A objTwo = new A(10);
여기서 인스턴스 objOne의 읽기 전용 필드 값은 5이고 objTwo의 값은 10입니다. const를 사용하면 불가능합니다.
상수는 리터럴 값으로 소비자에게 컴파일되는 반면 정적 문자열은 정의 된 값에 대한 참조로 사용됩니다.
연습으로 외부 라이브러리를 만들어 콘솔 응용 프로그램에서 사용하고 라이브러리의 값을 변경하고 다시 컴파일하십시오 (소비자 프로그램을 다시 컴파일하지 않고), DLL을 디렉토리에 드롭하고 EXE를 수동으로 실행하십시오. 상수 문자열은 변경되지 않습니다.
일정한
const 필드가 정의 될 때 값을 const 필드에 제공해야합니다. 그런 다음 컴파일러는 상수 값을 어셈블리의 메타 데이터에 저장합니다. 이것은 boolean, char, byte 등과 같은 기본 유형에 대해서만 상수를 정의 할 수 있음을 의미합니다. 상수는 인스턴스 멤버가 아니라 항상 정적 멤버로 간주됩니다.
읽기 전용
읽기 전용 필드는 런타임시에만 해결할 수 있습니다. 즉, 필드가 선언 된 유형의 생성자를 사용하여 값의 값을 정의 할 수 있습니다. 컴파일러가 읽기 전용 필드를 생성자 이외의 다른 방법으로 쓰지 않는지 확인합니다.
이 기사에서 여기에 설명 된 두 가지에 대한 자세한 내용
Const와 readonly는 비슷하지만 정확히 동일하지는 않습니다. const 필드는 컴파일 타임 상수입니다. 즉, 컴파일 타임에 해당 값을 계산할 수 있습니다. 읽기 전용 필드를 사용하면 유형을 구성하는 동안 일부 코드를 실행해야하는 추가 시나리오가 가능합니다. 구성 후에는 읽기 전용 필드를 변경할 수 없습니다.
예를 들어 const 멤버를 사용하여 다음과 같은 멤버를 정의 할 수 있습니다.
struct Test
{
public const double Pi = 3.14;
public const int Zero = 0;
}
3.14 및 0과 같은 값은 컴파일 타임 상수이므로 그러나 유형을 정의하고 일부 사전 팹 인스턴스를 제공하려는 경우를 고려하십시오. 예를 들어, Color 클래스를 정의하고 Black, White 등과 같은 일반적인 색상에 "상수"를 제공 할 수 있습니다. 오른쪽이 컴파일 타임 상수가 아니기 때문에 const 멤버를 사용하여이 작업을 수행 할 수 없습니다. 일반 정적 멤버 로이 작업을 수행 할 수 있습니다.
public class Color
{
public static Color Black = new Color(0, 0, 0);
public static Color White = new Color(255, 255, 255);
public static Color Red = new Color(255, 0, 0);
public static Color Green = new Color(0, 255, 0);
public static Color Blue = new Color(0, 0, 255);
private byte red, green, blue;
public Color(byte r, byte g, byte b) {
red = r;
green = g;
blue = b;
}
}
그러나 Color의 클라이언트가 Black과 White 값을 바꾸어 그것과 어울리는 것을 막을 수는 없습니다. 말할 것도없이, 이것은 Color 클래스의 다른 클라이언트들에게 혼란을 야기 할 것입니다. "읽기 전용"기능은이 시나리오를 해결합니다. 선언에 단순히 readonly 키워드를 도입함으로써 유연한 초기화를 유지하면서 클라이언트 코드가 혼동되지 않도록합니다.
public class Color
{
public static readonly Color Black = new Color(0, 0, 0);
public static readonly Color White = new Color(255, 255, 255);
public static readonly Color Red = new Color(255, 0, 0);
public static readonly Color Green = new Color(0, 255, 0);
public static readonly Color Blue = new Color(0, 0, 255);
private byte red, green, blue;
public Color(byte r, byte g, byte b) {
red = r;
green = g;
blue = b;
}
}
const 멤버는 항상 정적 인 반면, readonly 멤버는 일반 필드처럼 정적 일 수도 있고 그렇지 않을 수도 있습니다.
이 두 가지 목적으로 단일 키워드를 사용할 수 있지만 버전 문제 또는 성능 문제가 발생합니다. 우리가 이것을 위해 하나의 키워드를 사용했다고 가정하고 개발자는 다음과 같이 썼습니다.
public class A
{
public static const C = 0;
}
다른 개발자가 A에 의존하는 코드를 작성했습니다.
public class B
{
static void Main() {
Console.WriteLine(A.C);
}
}
이제 생성 된 코드가 AC가 컴파일 타임 상수라는 사실에 의존 할 수 있습니까? 즉, AC 사용을 단순히 값 0으로 대체 할 수 있습니까? "예"라고 대답하면 A 개발자가 AC 초기화 방식을 변경할 수 없음을 의미합니다. 이는 A 개발자의 권한을 무단으로 묶습니다. 이 질문에 "아니오"라고 말하면 중요한 최적화가 빠집니다. 아마도 A의 저자는 AC가 항상 0 일 것이라고 긍정적입니다. const와 readonly를 모두 사용하면 A 개발자가 의도를 지정할 수 있습니다. 따라서 버전 관리 동작이 향상되고 성능이 향상됩니다.
차이점은 정적 읽기 전용 필드의 값이 런타임에 설정되므로 프로그램 실행마다 다른 값을 가질 수 있다는 것입니다. 그러나 const 필드의 값은 컴파일 시간 상수로 설정됩니다.
알아두기 : 두 경우 모두 (정적 및 인스턴스) 참조 유형의 경우 읽기 전용 수정자는 필드에 새 참조를 할당하지 못하도록합니다. 구체적으로 참조로 가리키는 객체를 변경할 수 없습니다.
자세한 내용은이 항목에 대한 C # FAQ ( http://blogs.msdn.com/csharpfaq/archive/2004/12/03/274791.aspx) 를 참조하십시오.
사람들이 위에서 말한 것에 추가해야 할 한 가지. 읽기 전용 값을 포함하는 어셈블리가있는 경우 (예 : readonly MaxFooCount = 4;), 다른 버전으로 해당 어셈블리의 새 버전을 배송하여 호출 어셈블리가 보는 값을 변경할 수 있습니다 (예 : readonly MaxFooCount = 5;)
그러나 const를 사용하면 호출자가 컴파일 될 때 호출자의 코드로 접 힙니다.
이 수준의 C #에 도달하면 Bill Wagner의 저서 효과적인 C # : C #을 향상시키는 50 가지 방법 (이 49 가지 질문에 자세히 설명되어 있음)에 대한 준비가 된 것입니다.