etc./StackOverFlow

C#에서 const와 readonly의 차이점은 무엇입니까?

청렴결백한 만능 재주꾼 2022. 2. 27. 12:39
반응형

질문자 :readonly


C#에서 constreadonly 의 차이점은 무엇입니까?

언제 다른 것보다 하나를 사용하시겠습니까?



겉으로 보이는 차이 외에

  • const VS readonly 값을 정의할 때 값을 선언해야 하는 것은 동적으로 계산할 수 있지만 생성자가 종료되기 전에 할당해야 합니다. 그 후에는 고정됩니다.
  • const 는 암시적으로 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;

그러나 변경될 수 있는 상수가 있는 경우(egwrt 정밀도).. 의심스러운 readonly 사용하십시오.

 public readonly float PI = 3.14;

업데이트: Aku가 먼저 이것을 지적했기 때문에 언급을 받아야 합니다. 또한 나는 이것을 배운 곳에 연결해야 합니다: Effective C# - Bill Wagner


Gishu

const가 있는 문제가 있습니다! 다른 어셈블리에서 상수를 참조하는 경우 해당 값은 호출 어셈블리로 바로 컴파일됩니다. 그렇게하면 참조 된 어셈블리에서 상수를 업데이트 할 때 호출 어셈블리에서 변경되지 않습니다!


aku

상수

  • 상수는 기본적으로 정적입니다.
  • 컴파일 시 값이 있어야 합니다(예: 3.14 * 2를 가질 수 있지만 메서드를 호출할 수 없음).
  • 함수 내에서 선언 가능
  • 이를 사용하는 모든 어셈블리에 복사됩니다(모든 어셈블리는 값의 로컬 복사본을 얻음).
  • 속성에서 사용할 수 있습니다.

읽기 전용 인스턴스 필드

  • 생성자가 종료될 때까지 값을 설정해야 합니다.
  • 인스턴스가 생성될 때 평가됩니다.

정적 읽기 전용 필드

  • 코드 실행이 클래스 참조에 도달할 때 평가됩니다(새 인스턴스가 생성되거나 정적 메서드가 실행될 때).
  • 정적 생성자가 완료될 때까지 평가된 값이 있어야 합니다.
  • 여기에 ThreadStaticAttribute를 두는 것은 권장하지 않습니다(정적 생성자는 한 스레드에서만 실행되고 해당 스레드의 값을 설정합니다. 다른 모든 스레드는 이 값이 초기화되지 않음).

splattne

다만, 추가 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 } }

user1333

이것 은 그것을 설명 합니다 . 요약: const는 선언 시 초기화되어야 하고 readonly는 생성자에서 초기화될 수 있습니다(따라서 사용된 생성자에 따라 다른 값을 가짐).

편집: 미묘한 차이는 위의 Gishu's gotcha를 참조하십시오.


Vinko Vrsalovic

const : 어디에서나 변경할 수 없습니다.

readonly : 이 값은 생성자에서만 변경할 수 있습니다. 일반 기능에서는 변경할 수 없습니다.


Deepthi

상수 멤버는 컴파일 시 정의되며 런타임 시 변경할 수 없습니다. 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; } }

상수

  • static 으로 선언할 수 없습니다(암시적으로 정적임).
  • 상수 값은 컴파일 타임에 평가됩니다.
  • 상수는 선언 시에만 초기화됩니다.

읽기 전용

  • 인스턴스 수준 또는 정적일 수 있습니다.
  • 값은 런타임에 평가됩니다.
  • readonly는 선언 또는 생성자의 코드로 초기화할 수 있습니다.

Sujit

읽기 전용이 있는 작은 문제가 있습니다. 읽기 전용 필드는 생성자 내에서 여러 번 설정할 수 있습니다. 값이 두 개의 서로 다른 연결 생성자에 설정되어 있어도 여전히 허용됩니다.

 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 } }

Mike Two

const는 컴파일 타임 상수인 반면 readonly를 사용하면 런타임에 값을 계산하고 생성자 또는 필드 이니셜라이저에서 설정할 수 있습니다. 따라서 'const'는 항상 일정하지만 'readonly'는 일단 할당되면 읽기 전용입니다.

C# 팀의 Eric Lippert는 다양한 유형의 불변성에 대한 자세한 정보를 제공합니다.


Wheelie

다음은 const가 버전 안전하지 않거나 참조 유형과 관련이 없는 방법을 보여주는 또 다른 링크입니다.

요약 :

  • const 속성의 값은 컴파일 타임에 설정되며 런타임에는 변경할 수 없습니다.
  • Const는 정적으로 표시할 수 없습니다. 키워드는 정적으로 표시할 수 있는 읽기 전용 필드와 달리 정적임을 나타냅니다.
  • Const는 값(기본) 유형을 제외하고는 아무 것도 할 수 없습니다.
  • readonly 키워드는 필드를 변경할 수 없는 것으로 표시합니다. 그러나 속성은 클래스의 생성자 내에서 변경할 수 있습니다.
  • 읽기 전용 키워드는 static과 결합하여 const와 같은 방식으로 작동하도록 할 수도 있습니다(적어도 표면적으로는). 둘 사이의 IL을 보면 현저한 차이가 있습니다.
  • const 필드는 IL에서 "literal"로 표시되고 readonly는 "initonly"로 표시됩니다.

Chris S

읽기 전용 : 런타임 시 Ctor를 통해 값을 변경할 수 있습니다. 하지만 멤버 함수를 통해서가 아닙니다.

상수 : 기본적으로 정적입니다. 값은 어디에서나 변경할 수 없습니다(Ctor, Function, 런타임 등 없음).


Yeasin Abedin

또 다른 문제: 읽기 전용 값은 리플렉션을 통해 "비뚤어진" 코드로 변경할 수 있습니다.

 var fi = this.GetType() .BaseType .GetField("_someField", BindingFlags.Instance | BindingFlags.NonPublic); fi.SetValue(this, 1);

리플렉션을 사용하여 C#에서 개인 읽기 전용 상속 필드를 변경할 수 있습니까?


Greg

const 값이 모든 객체에 대해 동일하다고 생각하지만(리터럴 표현식으로 초기화해야 함), readonly 는 각 인스턴스화에 대해 다를 수 있습니다...


Daren Thomas

둘 다 일정하지만 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; } } }

Hallgrim

우리 사무실의 팀원 중 한 명이 const, static 및 readonly를 언제 사용해야 하는지에 대해 다음 지침을 제공했습니다.

  • 런타임에 알 수 있는 유형의 변수(문자열 리터럴, int, double, enums 등)가 있는 경우 클래스의 모든 인스턴스 또는 소비자가 값이 변경되지 않아야 하는 위치에 액세스할 수 있도록 하려는 경우 const를 사용합니다.
  • 클래스의 모든 인스턴스 또는 소비자가 값이 변경될 수 있는 위치에 액세스할 수 있도록 하려는 데이터가 있는 경우 static을 사용합니다.
  • 클래스의 모든 인스턴스 또는 소비자가 값이 변경되지 않아야 하는 위치에 액세스할 수 있도록 하려는 런타임(객체)에 알 수 없는 유형의 변수가 있는 경우 정적 읽기 전용을 사용합니다.
  • 변경되어서는 안 되는 객체 생성 시 알 수 있는 인스턴스 수준 변수가 있는 경우 읽기 전용을 사용합니다.

마지막 참고 사항: const 필드는 정적이지만 그 반대는 사실이 아닙니다.


Community Wiki

상수

  1. const 키워드는 필드 또는 지역 변수에 적용할 수 있습니다.
  2. 선언 시 const 필드를 할당해야 합니다.
  3. 할당된 메모리 없음 const 값은 컴파일 후 IL 코드 자체에 포함되어 있습니다. const 변수의 모든 항목을 찾아 해당 값으로 바꾸는 것과 같습니다. 따라서 컴파일 후 IL 코드는 const 변수 대신 하드 코딩된 값을 갖습니다.
  4. C#의 Const는 기본적으로 정적입니다.
  5. 값은 모든 개체에 대해 일정합니다.
  6. dll 버전 관리 문제가 있습니다. 즉, public const 변수 또는 속성을 변경할 때마다(사실, 이론적으로 변경되지 않아야 함) 이 변수를 사용하는 다른 dll 또는 어셈블리를 다시 빌드해야 합니다.
  7. C# 기본 제공 형식만 상수로 선언할 수 있습니다.
  8. Const 필드는 ref 또는 out 매개변수로 전달할 수 없습니다.

읽기 전용

  1. readonly 키워드는 지역 변수가 아닌 필드에만 적용됩니다.
  2. 선언 시 또는 생성자에서 읽기 전용 필드를 할당할 수 있으며 다른 메서드에서는 할당할 수 없습니다.
  3. 읽기 전용 필드에 동적 메모리가 할당되며 런타임에 값을 얻을 수 있습니다.
  4. Readonly는 생성된 객체에 속하므로 클래스의 인스턴스만 통해 액세스할 수 있습니다. 그것을 클래스 멤버로 만들려면 readonly 전에 static 키워드를 추가해야 합니다.
  5. 사용하는 생성자에 따라 값이 다를 수 있음(클래스의 객체에 속하므로)
  6. 기본이 아닌 유형(참조 유형)을 읽기 전용으로 선언하는 경우 참조는 포함된 개체가 아니라 변경할 수 없습니다.
  7. 값은 런타임에 얻어지기 때문에 읽기 전용 필드/속성에 dll 버전 문제가 없습니다.
  8. 생성자 컨텍스트에서 읽기 전용 필드를 ref 또는 out 매개변수로 전달할 수 있습니다.

Muhammad VP

  • const 또는 readonly 를 사용할 때

    • const

      • 컴파일 타임 상수: 절대 상수, 값은 선언 중에 설정되며 IL 코드 자체에 있습니다.
    • readonly

      • 런타임 상수: 구성 파일(예: App.config 통해 생성자/초기화에서 설정할 수 있지만 일단 초기화되면 변경할 수 없습니다.

Ryan Efendy

const로 표시된 변수는 강력한 형식의 #define 매크로에 불과하며 컴파일 시간에 const 변수 참조가 인라인 리터럴 값으로 대체됩니다. 결과적으로 특정 기본 제공 기본 값 유형만 이러한 방식으로 사용할 수 있습니다. 읽기 전용으로 표시된 변수는 런타임 시 생성자에서 설정할 수 있으며 해당 읽기 전용성은 런타임 중에도 적용됩니다. 이와 관련된 약간의 성능 비용이 있지만 이는 모든 유형(참조 유형 포함)에서 읽기 전용으로 사용할 수 있음을 의미합니다.

또한 const 변수는 본질적으로 정적이지만 읽기 전용 변수는 원하는 경우 인스턴스에 따라 다를 수 있습니다.


Wedge

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

readonly는 정적으로 선언할 수 있지만 필수는 아닙니다. 선언 시 초기화할 필요가 없습니다. 생성자를 사용하여 값을 할당하거나 변경할 수 있습니다. 따라서 인스턴스 클래스 멤버로 사용할 때 이점이 있습니다. 두 개의 다른 인스턴스화는 읽기 전용 필드의 값이 다를 수 있습니다. 예를 들어 -

 class A { public readonly int Id; public A(int i) { Id = i; } }

그런 다음 읽기 전용 필드는 다음과 같이 즉각적인 특정 값으로 초기화될 수 있습니다.

 A objOne = new A(5); A objTwo = new A(10);

여기에서 인스턴스 objOne은 readonly 필드 값이 5이고 objTwo는 10입니다. 이는 const를 사용하여 불가능합니다.


Chirag

또 다른 문제 .

const는 실제로 기본 데이터 유형에서만 작동하기 때문에 클래스로 작업하려는 경우 ReadOnly를 "강제로" 사용해야 한다고 느낄 수 있습니다. 그러나 함정을 조심하십시오! ReadOnly는 개체를 다른 개체로 바꿀 수 없음을 의미합니다(다른 개체를 참조하게 할 수 없음). 그러나 객체에 대한 참조가 있는 모든 프로세스는 객체 내부 의 값을 자유롭게 수정할 수 있습니다!

따라서 ReadOnly가 사용자가 변경할 수 없다는 것을 의미한다고 혼동하지 마십시오. C#에는 클래스의 인스턴스화에서 내부 값이 변경되는 것을 방지하는 간단한 구문이 없습니다(내가 아는 한).


Mark T

const하드 코딩 되어야 하며, readonly 는 클래스 생성자에서 설정할 수 있습니다.


Greg

상수는 리터럴 값으로 소비자에 컴파일되는 반면 정적 문자열은 정의된 값에 대한 참조 역할을 합니다.

연습으로 외부 라이브러리를 만들어 콘솔 응용 프로그램에서 사용한 다음 라이브러리의 값을 변경하고 다시 컴파일하고(소비자 프로그램을 다시 컴파일하지 않고) DLL을 디렉터리에 넣고 EXE를 수동으로 실행하면 다음을 찾아야 합니다. 상수 문자열은 변경되지 않습니다.


Brett Ryan

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 멤버는 일반 필드와 마찬가지로 정적이거나 그렇지 않을 수 있습니다.

이 두 가지 목적을 위해 단일 키워드를 사용할 수 있지만 이는 버전 문제나 성능 문제로 이어집니다. 우리가 이것(const)에 대해 단일 키워드를 사용했고 개발자가 다음과 같이 썼다고 잠시 가정합니다.

 public class A { public static const C = 0; }

다른 개발자는 A에 의존하는 코드를 작성했습니다.

 public class B { static void Main() { Console.WriteLine(AC); } }

이제 생성된 코드가 AC가 컴파일 타임 상수라는 사실에 의존할 수 있습니까? 즉, AC 사용을 단순히 값 0으로 대체할 수 있습니까? 이에 대해 "예"라고 말하면 A 개발자가 AC가 초기화되는 방식을 변경할 수 없음을 의미합니다. 이는 A 개발자의 손을 무단으로 묶는 것입니다. 이 질문에 "아니오"라고 말하면 중요한 최적화를 놓친 것입니다. 아마도 A의 저자는 AC가 항상 0일 것이라고 긍정적입니다. const와 readonly를 모두 사용하면 A 개발자가 의도를 지정할 수 있습니다. 이것은 더 나은 버전 관리 동작과 더 나은 성능을 제공합니다.


Ramesh Rajendran

ReadOnly : 값은 클래스의 생성자에서 한 번만 초기화됩니다.
const: 모든 함수에서 초기화할 수 있지만 한 번만


donstack

차이점은 정적 읽기 전용 필드의 값이 런타임에 설정되므로 프로그램 실행에 따라 다른 값을 가질 수 있다는 것입니다. 그러나 const 필드의 값은 컴파일 시간 상수로 설정됩니다.

기억하십시오: 참조 유형의 경우 두 경우 모두(정적 및 인스턴스) readonly 한정자는 필드에 새 참조를 할당하지 못하도록 막습니다. 특히 참조가 가리키는 객체를 불변으로 만들지 않습니다.

자세한 내용은 이 주제에 대한 C# 자주 묻는 질문을 참조하십시오. http://blogs.msdn.com/csharpfaq/archive/2004/12/03/274791.aspx


Yonatan Nir

상수 변수는 컴파일 타임에 선언되고 초기화됩니다. 와드 이후에는 값을 변경할 수 없습니다. 읽기 전용 변수는 클래스의 정적 생성자에서만 초기화됩니다. 읽기 전용은 런타임에 값을 할당하려는 경우에만 사용됩니다.


Omar AMEZOUG

주로; 정적 읽기 전용 필드에 값을 런타임에 상수가 아닌 값에 할당할 수 있는 반면 const에는 상수 값을 할당해야 합니다.


ljs

사람들이 위에서 말한 것에 한 가지를 추가합니다. 읽기 전용 값(예: readonly MaxFooCount = 4; )을 포함하는 어셈블리가 있는 경우 해당 어셈블리의 새 버전을 다른 값으로 배송하여 호출 어셈블리가 보는 값을 변경할 수 있습니다(예: readonly MaxFooCount = 5;).

그러나 const를 사용하면 호출자가 컴파일될 때 호출자의 코드로 접힐 것입니다.

이 수준의 C# 능숙도에 도달했다면 Bill Wagner의 책 Effective C#: 50 Specific Ways to Improve Your C#을 읽을 준비가 된 것입니다. 이 책에서는 이 질문에 대해 자세히 답변하고 있습니다.


Anthony

주요 차이점은 Const가 #DEFINE에 해당하는 C라는 것입니다. 숫자는 말 그대로 사전 컴파일러로 대체됩니다. 읽기 전용은 실제로 변수로 취급됩니다.

이 구분은 프로젝트 B의 Public 상수에 따라 Project A가 있는 경우 특히 관련이 있습니다. public 상수가 변경된다고 가정합니다. 이제 const/readonly 선택이 프로젝트 A의 동작에 영향을 줍니다.

Const: 프로젝트 A는 대체된 상수로 컴파일되었기 때문에 새 값을 포착하지 않습니다(물론 새 const로 다시 컴파일하지 않는 한).

읽기 전용: 프로젝트 A는 항상 프로젝트 B에 변수 값을 요청하므로 B에서 공개 상수의 새 값을 선택합니다.

솔직히 말해서, 진정한 보편적 상수(예: Pi, Inches_To_Centimeters)를 제외한 거의 모든 것에 대해 읽기 전용을 사용하는 것이 좋습니다. 변경될 수 있는 모든 것에 대해서는 readonly를 사용한다고 말합니다.

도움이 되기를 바랍니다, 앨런.


AlanR

Const : 애플리케이션 수명 동안 절대 상수 값입니다.

읽기 전용 : 실행 시간에 변경할 수 있습니다.


Bigeyes

출처 : http:www.stackoverflow.com/questions/55984/what-is-the-difference-between-const-and-readonly-in-c

반응형