c# - 형식이 - visual studio 2017.net framework



.Net 4.0 사용 이후 Visual Studio의 릴리스 모드에서 InvalidOperationException이 발생합니다. (1)

기존 .NET 3.5 응용 프로그램을 .NET 4.0으로 이식하는 데 문제가 있습니다. 본 강령은 혼자서 작성된 것이 아니므로 나는 왜 그런 것들이 존재하는지를 자세히 알지 못했습니다.

상황 : 코드가 잘 동작합니다 (릴리스 또는 디버그 모드는 중요하지 않습니다). 또한 응용 프로그램이 디버그 폴더에서 시작된 경우 문제가 릴리스 배포입니다. 4.0 이후 (그리고 4.5에서) 잘 작동합니다 : - /

이것은 초기 호출입니다.

someObject.Text = Elements.GetElement(Int16.Parse(cb1.Text));

그리고 코드는 다음과 같습니다.

public class Elements : EnumBase<int, Elements>
{
    public static readonly Elements Element1 = Create("Number 0", 0);
    public static readonly Elements Element2 = Create("Number 1", 1);

    private static Elements Create(string text, int value) 
    {
        return new Elements() { text = text, value = value };
    }

    public static String GetElement(int id)
    {

        // The Following Code safes the day and let the release deploy work fine.
        // It doesn´t matter if the condition becomes true or not to runtime.
        /* 
        if (id == 999999999)
        {
            Elements el = Element1;
        }
        */

        // Release deploy works also fine if you do the following line in a loop instead of linq.
        return BaseItemList.Single(v => v.Value == id).Text; 
    }
}

[Serializable()]
public class EnumBase<T, E> :  IEqualityComparer<E> 
        where E : EnumBase<T, E>
{
    private static readonly List<E> list = new List<E>();
    protected string text;
    protected T value;

    protected static IList<E> BaseItemList
    {
        get
        {
            return list.Distinct(new EnumBase<T, E>(false)).ToList();
        }
    }

    protected EnumBase()
    {
        list.Add(this as E);
    }

    /// <summary>
    /// Constructor for distinct to avoid empty elements in the list
    /// </summary>   
    private EnumBase(bool egal) {}

    public string Text
    {
        get { return text; }
    }

    public T Value
    {
        get { return value; }
    }


    #region IEqualityComparer<E> Member

    // ...

    #endregion
}

열쇠는 return BaseItemList.Single(v => v.Value == id).Text; . 릴리스에서 public static readonly Elements Element1 = Create("Number 0", 0); 이므로 public static readonly Elements Element1 = Create("Number 0", 0); InvalidOperationException public static readonly Elements Element1 = Create("Number 0", 0);public static readonly Elements Element2 = Create("Number 1", 1); 준비가 안됐어. 예외가 발생하면 BaseItemList가 비어 있습니다 (BaseItemList.Count = 0). 왜 이것이 비주얼 스튜디오의 릴리스 형태가 아닌 공개 형식의 bin-folder에서 발생했는지 나는 잘 모르겠습니다. 테스트의 경우 프로젝트 속성에서 "코드 최적화"를 비활성화했지만 도움이되지 않습니다.

확실히 구조가 최선은 아니지만, 코드가 더 평평하게 만드는 .Net 4.0에서 다른 점을 알고 싶습니다.

도와 주셔서 감사합니다

https://src-bin.com


Answer #1

난 문제가 당신이 그것에 대한 모든 필드를 참조하지 않은 사실에도 불구하고 실행중인 Elements 에 대한 정적 이니셜 라이저에 의존하는 것입니다 믿습니다. 정적 생성자가없는 형식의 형식 이니셜 라이저는 첫 번째 정적 필드 액세스 전에 만 실행되도록 보장됩니다. C # 5 섹션의 섹션 10.5.5.1 :

정적 생성자 (§10.12)가 클래스에 존재하면, 정적 필드 초기화 프로그램의 실행은 정적 생성자를 실행하기 직전에 발생합니다. 그 이외의 경우는, 정적 필드 이니셜 라이저는 해당 클래스의 정적 필드를 처음 사용하기 전에 구현 종속적 인 시간에 실행됩니다.

그리고 10.12 절은 다음과 같습니다 :

닫힌 클래스 유형의 정적 생성자는 주어진 응용 프로그램 도메인에서 최대 한 번만 실행됩니다. 정적 생성자의 실행은 응용 프로그램 도메인 내에서 발생하는 다음 이벤트 중 첫 번째 이벤트에 의해 트리거됩니다.

  • 클래스 유형의 인스턴스가 생성됩니다.
  • 클래스 유형의 모든 정적 멤버가 참조됩니다.

.NET 4 에서는 유형 초기화 구현이 변경 되었지만 구현 세부 사항 만있었습니다. 이전에는 코드가 손상되었지만 모르는 상태였습니다.

다음과 같이 코드를 변경하면 :

static Elements() {}

Elements 클래스에서 정적 인 생성자는 "첫 번째 필드 액세스 전에 어떤 지점에서"가 아니라 첫 번째 멤버 액세스 바로 전에 형식 초기화가 수행되기 때문에이 클래스가 작동한다고 믿습니다.

개인적으로 나는 일반적인 패턴에 대해 모호하지만 약간 다른 문제입니다.





release