참조 유형
생성자는 유형의 인스턴스를 좋은 상태로 초기화하는 특별한 방법입니다. 참조 유형의 인스턴스를 생성할 때 먼저 인스턴스의 데이터 필드에 메모리가 할당된 다음 추가 필드에 할당됩니다. 객체(유형 객체 포인터 및 동기화된 블록 인덱스)가 초기화되고 마지막으로 유형의 인스턴스 생성자를 호출하여 객체의 초기화 상태를 설정합니다.
참조 유형 객체를 생성할 때 객체에 할당된 메모리는 전기 영동 유형의 인스턴스 생성자 이전에 항상 0으로 재설정됩니다. 생성자에 의해 명시적으로 재정의되지 않은 모든 필드는 0 또는 null 값을 얻도록 보장됩니다.
다른 메서드와 달리 강도 생성자는 상속될 수 없습니다. 즉, 클래스에는 클래스 자체에서 정의한 부드러운 생성자만 있습니다. 인스턴스 생성자는 상속될 수 없으므로 가상, 신규, 재정의, 봉인 및 추상 수정자는 인스턴스 생성자에서 사용할 수 없습니다. 클래스가 생성자를 명시적으로 정의하지 않는 경우 C# 컴파일러는 기본적으로 매개 변수가 없는 생성자를 구현하며 기본 클래스의 매개 변수가 없는 생성자를 호출합니다.
클래스의 수정자가 추상이면 컴파일러에서 생성된 기본 생성자의 접근성은 제품입니다. 그렇지 않으면 생성자에 공용 액세스 가능 속성이 할당됩니다. 기본 클래스가 매개 변수 없는 생성자를 제공하지 않는 경우 파생 클래스는 기본 클래스 생성자를 명시적으로 호출해야 합니다. 그렇지 않으면 컴파일러에서 오류를 보고합니다. 클래스 수정자가 정적(봉인 및 추상)인 경우 컴파일러는 클래스 정의에 기본 생성자를 전혀 생성하지 않습니다.
유형은 여러 인스턴스 생성자를 정의할 수 있습니다. 각 생성자는 서로 다른 시그니처를 가져야 하며 각각 서로 다른 액세스 가능 속성을 가질 수 있습니다. 코드를 "검증 가능"하게 만들기 위해 클래스의 초기화 프로그램은 기본 클래스에서 상속된 필드에 액세스하기 전에 기본 클래스의 생성자를 호출해야 합니다. 파생 클래스 생성자가 기본 클래스 생성자를 명시적으로 호출하지 않는 경우 C# 컴파일러는 기본 기본 클래스 생성자에 대한 호출을 자동으로 생성합니다. 결국 System.Object의 인수 없는 공용 생성자가 호출됩니다. 생성자는 아무 작업도 수행하지 않고 직접 반환합니다. System.Object에는 인스턴스 데이터 필드가 없으므로 해당 생성자는 아무 작업도 수행하지 않습니다.
드물게 인스턴스 생성자를 호출하지 않고 유형 인스턴스를 생성하는 것이 가능합니다. 일반적인 예는 Object의 MemberwiseClone 메서드입니다. 이 메서드가 수행하는 작업은 메모리를 할당하고 개체의 추가 필드를 초기화한 다음 원본 개체의 자체 데이터를 새 개체에 복사하는 것입니다. 또한 런타임 직렬 변환기를 사용하여 개체를 역직렬화하는 경우 동일한 프로세스에서 생성자를 호출할 필요가 없습니다. 역직렬화는 System.Runtime.Serialization.FormatterServices 형식의 GetUnnitalizedObject 또는 GetSafeUninitailizedObject 메서드를 사용하여 개체에 대한 메모리를 할당하며 생성자는 프로세스 중에 호출되지 않습니다.
팁:
생성자에서 가상 메서드를 호출하지 마세요. 그 이유는 인스턴스화된 타입이 가상 메소드를 오버라이드하면 파생 타입의 가상 메소드 구현이 실행되지만 이때 상속 계층 구조의 모든 필드에 대한 초기화가 완료되지 않았기 때문이다(인스턴스화된 타입의 생성자) 아직 실행되지 않음). 따라서 가상 메서드를 호출하면 예측할 수 없는 동작이 발생할 수 있습니다. 결국 이는 가상 메소드가 호출될 때 해당 메소드가 실행되는 실제 유형이 런타임까지 선택되지 않기 때문입니다.
값 유형(구조체) 생성자
값 유형(구조체) 생성자는 참조 유형(클래스)의 생성자와 완전히 다르게 작동합니다. CLR은 항상 값 유형의 인스턴스 생성을 허용하며 값 유형의 인스턴스화를 방지할 수 있는 방법은 없습니다. 따라서 값 형식은 실제로 생성자를 정의할 필요가 없으며 C# 컴파일러는 값 형식에 대해 인수가 없는 기본 생성자를 전혀 인라인하지 않습니다. 다음 코드를 보세요:
internal struct Point {
public int m_x, m_y;
}
internal sealing class Reactangel
{
public Point m_TopLeft, m_bottomRight;
}
Con 직사각형 구조화 , new 연산자를 사용해야 하며 생성자를 지정해야 합니다. 이 예제에서는 C# 컴파일러에서 자동으로 생성된 기본 생성자가 호출됩니다. Point 값 유형의 인스턴스 두 개를 포함하는 Reatangle에 메모리를 할당합니다. 성능을 고려하여 CLR은 참조 유형에 포함된 각 값 유형 필드에 대해 생성자를 적극적으로 호출하지 않습니다. 그러나 앞서 언급한 대로 값 유형 필드는 0 또는 null로 초기화됩니다.
CLR에서는 값 유형에 대해 생성자를 정의할 수 있지만 실행하려면 생성자를 명시적으로 호출해야 합니다.
내부 구조체 포인트 {
public int m_x, m_y;
public Point(int x, int y)
{
m_x = x;
m_y = y;
}
}
내부 봉인 클래스 Reactangel
{
public Point m_TopLeft, m_bottomRight;
public Reactangel()
{
this.m_TopLeft = new Point(1,2);
this.m_bottomRight = new Point(100) , 200 );
}
}
값 유형의 인스턴스 생성자는 명시적으로 호출되는 경우에만 실행됩니다. 따라서 Rectangle의 생성자가 New 연산자를 사용하여 Point의 생성자를 호출하여 Reatangle의 m_TopLeft 및 m_bottomRight 필드를 초기화하지 않으면 두 포인트 필드의 m_x 및 m_y 필드는 모두 0이 됩니다.
위를 다시 작성하세요. 코드 :
내부 구조체 포인트 {
public int m_x, m_y;
public Point()
{
m_x = 5;
m_y = 6;
}
}
내부 Sealed class Reactangel
{
public Point m_TopLeft, m_bottomRight;
public Reactangel()
{
}
}
이제 새로운 Rectangle 클래스를 생성할 때 두 Point 필드에 m_x 및 m_y 필드가 있습니다. 얼마나 초기화되나요? 0인가요, 5인가요?
C# 컴파일러가 Reactangel의 생성자에서 코드를 생성하고 Reactangel의 두 필드에 대해 Point의 기본 인수 없는 생성자를 자동으로 호출한다고 생각할 수도 있습니다. 그러나 애플리케이션의 런타임 성능을 향상시키기 위해 C# 컴파일러는 이러한 코드를 자동으로 생성하지 않습니다. 실제로 값 형식이 매개 변수 없는 생성자를 제공하더라도 많은 컴파일러에서는 이를 호출하는 코드를 생성하지 않습니다. 값 형식 매개 변수 없는 생성자를 구현하려면 개발자가 값 형식 생성자를 명시적으로 호출하는 코드를 추가해야 합니다. 그런데 이런 이유로 Point'의 두 필드가 0으로 초기화됩니까? 결과는 다음과 같습니다.
C# 컴파일러는 개발자가 이러한 생성자가 호출될 때 혼동되는 것을 방지하기 위해 값 유형이 매개 변수 없는 생성자를 정의하는 것을 의도적으로 허용하지 않습니다. 매개 변수 없는 생성자를 정의할 수 없으므로 컴파일러는 이를 자동으로 호출하는 코드를 생성하지 않습니다. 매개 변수 없는 생성자가 없으면 값 형식의 필드는 항상 0 또는 null로 초기화됩니다.
유형 생성자:
정적 생성자, 클래스 생성자 또는 유형 초기화라고도 합니다. 유형 생성자는 참조 유형 및 값 유형과 함께 사용할 수 있습니다. 인스턴스 생성자의 목적은 유형 인스턴스의 초기 상태를 설정하는 것입니다. 따라서 유형 생성자의 역할은 유형의 초기 상태를 설정하는 것입니다. 유형은 기본적으로 유형 생성자를 정의하지 않습니다. 정의된 경우 하나만 있을 수 있습니다. 게다가 유형 생성자에는 매개변수가 없습니다.
internal sealing class SomeRefType {
static SomeRefType()
{
//처음 접속시 여기 코드를 실행하세요
}
}
internal struct SomeValType
{
정적 SomeValType()
{
//처음 방문 시 여기에서 코드를 실행하세요
}
}
타입 생성자를 정의하는 것은 매개변수 없는 인스턴스 생성자를 정의하는 것과 비슷하지만 차이점은 다음과 같습니다. static으로 표시되어야 합니다. 게다가 유형 생성자는 항상 비공개입니다. 비공개인 이유는 개발자가 코드를 작성하여 이를 호출하는 것을 방지하기 위함이며 CLR은 항상 그의 호출에 대한 책임이 있습니다.
팁:
값 유형에서 유형 생성자를 정의할 수 있지만 CLR이 때때로 값 유형의 정적 생성자를 호출하지 않기 때문에 실제로 그렇게 해서는 안 됩니다. 예를 들어
internal struct SomeValType
{
static SomeValType()
{
Console.WriteLine("이 문장은 표시되지 않습니다.");
}
public int m_x;
}
class Program
{
static void Main(string [ ] args)
{
SomeValType[] a = new SomeValType[10];
a[0].m_x = 123;
Console.WriteLine(a[0].m_x);
Console.ReadKey ( );
}
}
유형 생성자의 코드는 유형의 정적 필드에만 액세스할 수 있으며, 이 코드의 특이한 용도는 이러한 필드를 초기화하는 것입니다.
위 내용은 생성자란 무엇입니까? 참조 유형은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!