代码之家  ›  专栏  ›  技术社区  ›  Sumchans

在C#中对属性的set方法调用函数会抛出系统。栈溢出异常

  •  1
  • Sumchans  · 技术社区  · 3 年前

    c#新手。这是我正在使用的json的示例。目标是将两个字母的标志代码转换为标志表情符号。

    [
        {
          "name": "American Samoa",
          "flag": "🇦🇸",
          "code": "AS",
          "dialcode": "+1684"
        },
        {
          "name": "Andorra",
          "flag": "🇦🇩",
          "code": "AD",
          "dialcode": "+376"
        },
    ]
    

    下面的代码将两个字母的国家代码从json文件转换为标志表情符号。我正在调用一个方法,该方法实际上对Flag属性的set方法进行转换。运行此代码会引发一个系统。StackOverflow异常。

    using Newtonsoft.Json;
        
    namespace Bol.Models
    {
        internal class Countries
        {
            public List<Country> CountriesInfo { get; set; }
            public Countries()
            {
                StreamReader r = new StreamReader("C:\\Users\\folder\\Desktop\\Bol\\Bol\\Resources\\Data\\Countries.json");
                string jsonString = r.ReadToEnd();
                CountriesInfo = JsonConvert.DeserializeObject<List<Country>>(jsonString);           
            }
            
        }
    
        internal class Country
        {
            public string Name { get; set; }
            public string Flag { get { return Flag; } set { Flag = IsoCountryCodeToFlagEmoji(value); } }
            public string Code { get; set; }
            public string Dialcode { get; set; }
    
            public string IsoCountryCodeToFlagEmoji(string countryCode) => string.Concat(countryCode.ToUpper().Select(x => char.ConvertFromUtf32(x + 0x1F1A5)));
        }  
    }
    
    1 回复  |  直到 3 年前
        1
  •  3
  •   ProgrammingLlama Raveena Sarda    3 年前
    public string Flag
    {
        get { return Flag; }
        set { Flag = IsoCountryCodeToFlagEmoji(value); }
    }
    

    让我们在这里查看您的代码。

    • get :获取值的调用 Flag 将必须调用以获取的值 旗帜 属性,它将调用以获取的值 旗帜 属性处于无限循环中。
    • set :用于设置值的调用 旗帜 将尝试为分配一个值 旗帜 属性,它将尝试为 旗帜 属性处于无限循环中。

    你需要一个后备场。

    private string _flag;
    
    public string Flag
    {
        get { return _flag; }
        set { _flag = IsoCountryCodeToFlagEmoji(value); }
    }
    

    不过,我建议或许拥有两处房产,因为 旗帜 属性当前正在转换您输入的值,以便 收到 不是你想要的 设置 。您可以有一个用于国家代码,一个用于国旗:

    private string _countryCode;
    
    public string CountryCode
    {
        get { return _countryCode; }
        set
        {
            _countryCode = value;
            Flag = IsoCountryCodeToFlagEmoji(value);
        }
    }
    
    public string Flag { get; private set; }
    

    这将计算 旗帜 当时 CountryCode 已设置。或者,你可以每次都计算 旗帜 被访问:

    public string CountryCode { get; set; }
    public string Flag { get { return IsoCountryCodeToFlagEmoji(CountryCode); } }
    // or public string Flag => IsoCountryCodeToFlagEmoji(CountryCode);
    

    关于你的问题“我不是也在对其他房产做什么吗?”:不,不是。

    当编译时, public string Name { get; set; } 变成这样:

    [CompilerGenerated]
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private string <Name>k__BackingField;
    
    public string Name
    {
        [CompilerGenerated]
        get
        {
            return <Name>k__BackingField;
        }
        [CompilerGenerated]
        set
        {
            <Name>k__BackingField = value;
        }
    }
    

    注意到它有一个单独的背景字段吗?现在让我们将其与您的 旗帜 属性被编译为:

    public string Flag
    {
        get
        {
            return Flag;
        }
        set
        {
            Flag = IsoCountryCodeToFlagEmoji(value);
        }
    }
    

    注意到没有背景场吗?

    您可以看到编译(然后反编译,因为C#是编译到中间语言的)版本 here

    请注意,成员名称带有 < > 在IL中有效,但在C#中无效,因此编译器的代码生成使用这些来避免与您编写的代码发生冲突。