다음을 통해 공유


CA1810: 참조 형식 정적 필드를 인라인으로 초기화하십시오.

속성
규칙 ID CA1810
제목 참조 형식 정적 필드를 인라인으로 초기화하세요.
범주 성능
수정 사항이 주요 변경인지 여부 주요 변경 아님
.NET 8에서 기본적으로 사용 아니요

원인

참조 형식이 명시적 정적 생성자를 선언합니다.

규칙 설명

형식이 명시적인 정적 생성자를 선언하면 JIT(Just-in-Time) 컴파일러는 형식의 각 정적 메서드와 인스턴스 생성자에 검사를 추가하여 정적 생성자를 이전에 호출했는지 확인합니다. 정적 초기화는 정적 멤버에 액세스하거나 형식의 인스턴스를 만들 때 트리거됩니다. 그러나 형식의 변수를 선언하지만 사용하지 않는 경우에는 정적 초기화가 트리거되지 않습니다. 이는 초기화로 인해 전역 상태가 변경되는 경우 중요할 수 있습니다.

모든 정적 데이터가 인라인으로 초기화되고 명시적 정적 생성자가 선언되지 않은 경우 CIL(공용 중간 언어) 컴파일러는 플래그와 정적 데이터를 초기화하는 암시적 정적 생성자를 CIL 형식 정의에 추가 beforefieldinit 합니다. JIT 컴파일러가 beforefieldinit 플래그를 발견하면 정적 생성자가 확인하는 대부분의 시간이 추가되지 않습니다. 정적 초기화는 정적 메서드나 인스턴스 생성자가 호출되기 전이 아니라 정적 필드에 액세스하기 전에 수행되도록 보장됩니다. 정적 초기화는 형식의 변수가 선언된 후 언제든지 수행될 수 있습니다.

정적 생성자 검사로 인해 성능이 저하될 수 있습니다. 보통 정적 생성자는 정적 필드를 초기화하는 데만 사용됩니다. 이 경우 정적 필드의 첫 번째 액세스 이전에 정적 초기화가 수행되는지 확인해야 합니다. beforefieldinit 동작은 이러한 형식 및 대부분의 다른 형식에 적합합니다. 정적 초기화가 전역 상태에 영향을 주고 다음 중 하나를 충족하는 경우에만 부적합합니다.

  • 전역 상태 효과는 비용이 많이 들고 형식이 사용되지 않는 경우에는 필요하지 않습니다.

  • 형식의 정적 필드에 액세스하지 않고 전역 상태 효과에 액세스할 수 있습니다.

위반 문제를 해결하는 방법

이 규칙 위반 문제를 해결하려면 모든 정적 데이터를 선언할 때 초기화하고 정적 생성자를 제거합니다.

경고를 표시하지 않는 경우

다음 중 하나가 적용되는 경우 이 규칙에서 경고를 표시하지 않는 것이 안전합니다.

  • 성능은 문제가 되지 않습니다.
  • 정적 초기화로 인해 발생하는 전역 상태 변경은 비용이 많이 들거나 형식의 정적 메서드를 호출하거나 형식의 인스턴스를 만들기 전에 발생하도록 보장해야 합니다.

경고 표시 안 함

단일 위반만 표시하지 않으려면 원본 파일에 전처리기 지시문을 추가하여 규칙을 사용하지 않도록 설정한 후 다시 사용하도록 설정합니다.

#pragma warning disable CA1810
// The code that's violating the rule is on this line.
#pragma warning restore CA1810

파일, 폴더 또는 프로젝트에 대한 규칙을 사용하지 않도록 설정하려면 구성 파일에서 심각도를 none으로 설정합니다.

[*.{cs,vb}]
dotnet_diagnostic.CA1810.severity = none

자세한 내용은 방법: 코드 분석 경고 표시 안 함을 참조하세요.

예시

다음 예제에서는 규칙을 위반하는 형식인 StaticConstructor 및 정적 생성자를 인라인 초기화로 바꿔 규칙을 충족하는 형식인 NoStaticConstructor를 보여 줍니다.

public class StaticConstructor
{
    static int someInteger;
    static string? resourceString;

    static StaticConstructor()
    {
        someInteger = 3;
        ResourceManager stringManager =
           new ResourceManager("strings", Assembly.GetExecutingAssembly());
        resourceString = stringManager.GetString("string");
    }

    public void Print()
    {
        Console.WriteLine(someInteger);
    }
}

public class NoStaticConstructor
{
    static int someInteger = 3;
    static string? resourceString = InitializeResourceString();

    static string? InitializeResourceString()
    {
        ResourceManager stringManager =
           new ResourceManager("strings", Assembly.GetExecutingAssembly());
        return stringManager.GetString("string");
    }

    public void Print()
    {
        Console.WriteLine(someInteger);
    }
}
Imports System
Imports System.Resources

Namespace ca1810

    Public Class StaticConstructor

        Shared someInteger As Integer
        Shared resourceString As String

        Shared Sub New()

            someInteger = 3
            Dim stringManager As New ResourceManager("strings",
            System.Reflection.Assembly.GetExecutingAssembly())
            resourceString = stringManager.GetString("string")

        End Sub

    End Class


    Public Class NoStaticConstructor

        Shared someInteger As Integer = 3
        Shared resourceString As String = InitializeResourceString()

        Private Shared Function InitializeResourceString()

            Dim stringManager As New ResourceManager("strings",
            System.Reflection.Assembly.GetExecutingAssembly())
            Return stringManager.GetString("string")

        End Function

    End Class

End Namespace

클래스에 beforefieldinit 대한 CIL 정의에 플래그를 추가합니다 NoStaticConstructor .

.class public auto ansi StaticConstructor
extends [mscorlib]System.Object
{
} // end of class StaticConstructor

.class public auto ansi beforefieldinit NoStaticConstructor
extends [mscorlib]System.Object
{
} // end of class NoStaticConstructor