programing

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

mailnote 2023. 5. 1. 21:42
반응형

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

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

당신은 언제 그것을 다른 것보다 사용할 것입니까?

의 명백한 차이를 제외하고는

  • 다음에 대한 정의 시 값을 선언해야 합니다.const »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;
  }
}

AssemblyBAssemblyA코드에 이러한 값을 사용합니다.이것이 컴파일될 때:

  • 의경에는의 const값입니다. 대체 찾기와 같습니다.값2는 '베이됩킹'니다 ''▁2됩'로 '.AssemblyBIL. 하면 ' 의 IL. 즉일내내업데를가트이,▁'▁'즉를업트데이▁if내s.I_CONST_VALUE다시 컴파일할 때까지 2개가 남아있을 겁니다
  • 의경에는의 readonly가치, 그것은 a와 같습니다.ref메모리 위치로 이동합니다.값이 구워지지 않습니다.AssemblyBIL. 되면 '의 IL. ', 의리즉위업, 되면트이데가치메모,면▁'되즉트.AssemblyB다시 컴파일하지 않고 새 값을 가져옵니다.그래서 만약에I_RO_VALUE30으로 업데이트되었습니다. 빌드만 하면 됩니다.AssemblyA모든 클라이언트를 다시 컴파일할 필요가 없습니다.

따라서 상수 값이 변경되지 않을 것으로 확신할 경우 다음을 사용합니다.const.

public const int CM_IN_A_METER = 100;

상수가 할 수 또는 에는 합니다.readonly.

public readonly float PI = 3.14;

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

컨스트가 있는 갓챠가 있습니다!다른 어셈블리에서 상수를 참조하면 해당 값이 호출 어셈블리로 바로 컴파일됩니다.그러면 참조된 어셈블리에서 상수를 업데이트할 때 호출 어셈블리에서 상수가 변경되지 않습니다!

상수

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

읽기 전용 인스턴스 필드

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

정적 읽기 전용 필드

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

덧이자면붙.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
  }
}

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

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

이것으로 설명할 수 있습니다.요약: const는 선언 시 초기화되어야 하며, read only는 생성자에서 초기화될 수 있습니다(따라서 사용된 생성자에 따라 값이 다릅니다).

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

상수 멤버는 컴파일 시간에 정의되며 런타임에 변경할 수 없습니다.상는다사필선언드다니됩로여를 됩니다.const키워드이며 선언된 대로 초기화해야 합니다.

public class MyClass
{
    public const double PI1 = 3.14159;
}

A readonly멤버는 불변의 값을 나타낸다는 점에서 상수와 같습니다.입니다.readonly구성원은 생성자에서 런타임에 초기화될 수 있을 뿐만 아니라 선언된 대로 초기화될 수 있습니다.

public class MyClass1
{
     public readonly double PI2 = 3.14159;

     //or

     public readonly double PI3;

     public MyClass2()
     {
         PI3 = 3.14159;
     }
}

컨스

  • 다▁as다로 선언될 수 없습니다.static은 암묵적으로 정적입니다
  • 상수 값은 컴파일 시 평가됩니다.
  • 선언 시에만 상수가 초기화됩니다.

읽기 전용

  • 인스턴스 레벨 또는 정적일 수 있습니다.
  • 이 값은 실행 시 평가됩니다.
  • 읽기 전용은 선언이나 생성자의 코드로 초기화할 수 있습니다.

읽기 전용의 작은 갓챠가 있습니다.읽기 전용 필드는 생성자 내에서 여러 번 설정할 수 있습니다.값이 서로 다른 두 체인 생성자에서 설정된 경우에도 여전히 허용됩니다.

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'는 항상 일정하지만 'read only'는 할당되면 읽기 전용입니다.

C# 팀의 Eric Lippert는 다양한 유형의 불변성에 대한 더 많은 정보를 가지고 있습니다.

다음 링크는 const가 버전 안전하지 않거나 참조 유형과 관련이 있는지 보여줍니다.

요약:

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

읽기 전용 : 실행 시 Ctor를 통해 값을 변경할 수 있습니다.하지만 회원 기능을 통해가 아닙니다.

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

그러나 또 다른 문제는 읽기 전용 값이 반사를 통해 "devious" 코드에 의해 변경될 수 있다는 점입니다.

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

반사를 사용하여 C#에서 상속된 개인 읽기 전용 필드를 변경할 수 있습니까?

는 는나믿습다니▁a▁believe다니를 믿습니다.const개체에 . 에 값모 든 개 대 식 초 문 로 으 기 합 어 니 야 다 되 화 자 은 며 동 하 체 일 에 해 ▁value 니 합 다 ▁( and ▁is 값 야 ▁whereas ized▁with은어 ▁objects 초 ▁the되ion기화readonly인스턴스화마다 다를 수 있습니다...

우리 사무실의 팀원 중 한 명이 const, static 및 read only를 사용하는 경우에 대해 다음과 같은 지침을 제공했습니다.

  • 클래스의 모든 인스턴스 또는 소비자가 값이 변경되지 않아야 하는 위치에 액세스할 수 있도록 런타임에 알 수 있는 유형의 변수(문자열 리터럴, int, 이중, 열거형 등)가 있는 경우 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또는readonly

    • const

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

      • 런타임 상수: 구성 파일을 통해 생성자/init에서 설정할 수 있습니다. App.config 일단 수 .

CONST

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

읽기 전용

  1. 읽기 전용 키워드는 로컬 변수가 아닌 필드에만 적용됩니다.
  2. 선언 시 또는 생성자에서 읽기 전용 필드를 할당할 수 있으며, 다른 방법으로는 할당할 수 없습니다.
  3. 동적 메모리가 읽기 전용 필드에 할당되어 실행 시 값을 가져올 수 있습니다.
  4. 읽기 전용은 클래스의 인스턴스를 통해서만 액세스할 수 있도록 만든 개체에 속합니다.클래스 멤버로 만들려면 읽기 전용 전에 정적 키워드를 추가해야 합니다.
  5. 클래스의 개체에 속하므로 사용된 생성자에 따라 값이 다를 수 있습니다.
  6. 기본이 아닌 유형(참조 유형)을 읽기 전용으로 선언하는 경우 참조는 포함된 개체가 아니라 불변입니다.
  7. 이 값은 런타임에 가져오기 때문에 읽기 전용 필드/속성에 대한 dll 버전 관리 문제가 없습니다.
  8. 생성자 컨텍스트에서 refout 매개 변수로 읽기 전용 필드를 전달할 수 있습니다.

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

또한 상수 변수는 본질적으로 정적인 반면 읽기 전용 변수는 원하는 경우 인스턴스에 특정될 수 있습니다.

C#의 const 필드와 read only 필드 사이에는 현저한 차이가 있습니다.그물

const는 기본적으로 정적이므로 나중에 수정할 수 없는 상수 값으로 초기화해야 합니다.생성자에서도 값 변경이 허용되지 않습니다.모든 데이터 유형에 사용할 수는 없습니다.이전 날짜 시간입니다.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를 사용해서는 불가능합니다.

또 한 은 잡았습니다.

const는 실제로 기본 데이터 유형에서만 작동하므로 클래스에서 작업하려면 "읽기 전용"을 사용해야 한다고 느낄 수 있습니다.하지만, 덫을 조심하세요!읽기 전용은 개체를 다른 개체로 바꿀 수 없음을 의미합니다(다른 개체를 참조하도록 만들 수 없음).그러나 개체에 대한 참조가 있는 모든 프로세스는 개체 내부의 을 자유롭게 수정할 수 있습니다!

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

A const하드 코딩해야 합니다. 반면에readonly클래스의 생성자에서 설정할 수 있습니다.

상수는 리터럴 값으로 소비자에 컴파일되고 정적 문자열은 정의된 값에 대한 참조로 사용됩니다.

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

상수와 읽기 전용은 비슷하지만 정확히 동일하지는 않습니다.const 필드는 컴파일 시간 상수이며, 이는 해당 값이 컴파일 시간에 계산될 수 있음을 의미합니다.읽기 전용 필드를 사용하면 형식을 구성하는 동안 일부 코드를 실행해야 하는 추가 시나리오를 사용할 수 있습니다.구성 후에는 읽기 전용 필드를 변경할 수 없습니다.

예를 들어, const 멤버는 다음과 같은 멤버를 정의하는 데 사용될 수 있습니다.

struct Test
{
    public const double Pi = 3.14;
    public const int Zero = 0;
}

3.14 및 0과 같은 값은 컴파일 시간 상수이기 때문입니다.그러나 유형을 정의하고 팹 이전 인스턴스를 제공하려는 경우를 고려해 보십시오. 예를 들어, 색상 클래스를 정의하고 검정, 흰색 등과 같은 일반 색상에 대해 "정수"를 제공할 수 있습니다.오른쪽이 컴파일 시간 상수가 아니기 때문에 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;
    }
}

그러나 Black and White 값을 스왑하여 Color 클라이언트가 이 클라이언트와 충돌하는 것을 방지할 수는 없습니다.말할 필요도 없이, 이것은 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 멤버는 항상 정적인 반면, 읽기 전용 멤버는 일반 필드와 마찬가지로 정적이거나 아닐 수 있습니다.

이 두 가지 목적으로 단일 키워드를 사용할 수 있지만 버전 문제나 성능 문제가 발생할 수 있습니다.여기에 단일 키워드(const)를 사용하여 개발자가 다음과 같이 기술했다고 가정합니다.

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

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

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

이제 생성된 코드가 A라는 사실에 의존할 수 있습니까?C는 컴파일 시간 상수입니까?즉, A를 사용할 수 있습니까?C는 단순히 값 0으로 대체됩니까?만약 당신이 이것에 대해 "예"라고 말한다면, 그것은 A의 개발자가 A의 방식을 바꿀 수 없다는 것을 의미합니다.C는 초기화되어 있습니다. 이것은 허가 없이 A 개발자의 손을 묶습니다.이 질문에 "아니오"라고 대답하면 중요한 최적화가 누락됩니다.아마도 A의 저자는 A에 대해 긍정적일 것입니다.C는 항상 0입니다.const와 read만 사용하면 A의 개발자는 의도를 지정할 수 있습니다.이를 통해 버전 작업 및 성능이 향상됩니다.

전용 "읽기":값은 클래스의 생성자에서 한 번만 초기화됩니다.
const할 수 const:는 한 번만 초기화할 수 .

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

기억:참조 유형의 경우(정적 및 인스턴스) 읽기 전용 한정자를 사용하면 필드에 새 참조를 할당할 수 없습니다.구체적으로 참조에 의해 가리킨 객체를 불변으로 만들지 않습니다.

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

기본적으로 정적 읽기 전용 필드에 대한 값을 런타임에 상수가 아닌 값에 할당할 수 있지만 상수에는 상수 값을 할당해야 합니다.

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

그러나 상수를 사용하면 호출자가 컴파일될 때 호출자의 코드로 접힙니다.

만약 여러분이 이 C# 수준에 도달했다면, 여러분은 빌 와그너의 책 "효과적인 C#: 여러분의 C#을 향상시키는 50가지 구체적인 방법들"에 대한 준비가 되어 있습니다. 이것은 이 질문에 자세히 답합니다. (그리고 49가지 다른 것들)

주요 차이점은 Const가 #DEFINE의 C에 해당한다는 것입니다.이 숫자는 문자 그대로 a-la 프리 컴파일러로 대체됩니다.읽기 전용은 실제로 변수로 처리됩니다.

이 구분은 프로젝트 B의 공용 상수에 따라 프로젝트 A가 있을 때 특히 유용합니다.공용 상수가 변경된다고 가정합니다.이제 const/readonly를 선택하면 프로젝트 A의 동작에 영향을 미칩니다.

Const: 프로젝트 A는 부제된 상수로 컴파일되었기 때문에 (물론 새 const로 재컴파일되지 않는 한) 새 값을 얻지 못합니다.

읽기 전용: 프로젝트 A는 항상 프로젝트 B에 변수 값을 묻기 때문에 프로젝트 B에서 공용 상수의 새 값을 선택합니다.

솔직히, 저는 진정한 보편적 상수(예: 파이, 인치_)를 제외한 거의 모든 것에 대해 읽기 전용을 사용할 것을 권장합니다.대상(_cm).변경될 수 있는 모든 사항에 대해서는 읽기 전용을 사용합니다.

이게 도움이 되길 바래, 앨런.

상수: 응용 프로그램 수명 동안 절대 상수 값입니다.

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

읽기 전용 필드의 값을 변경할 수 있습니다.그러나 const 필드의 값은 변경할 수 없습니다.

읽기 전용 필드에서는 선언 시 또는 해당 클래스의 생성자에 값을 할당할 수 있습니다.상수의 경우 선언 시에만 값을 할당할 수 있습니다.

정적 한정자에는 읽기 전용을 사용할 수 있지만 정적에는 상수를 사용할 수 없습니다.

언급URL : https://stackoverflow.com/questions/55984/what-is-the-difference-between-const-and-readonly-in-c

반응형