当使用get set属性时出现System.StackOverflowException异常?

17

代码如下所示。

发生了类型为 "System.StackOverflowException" 的未处理异常,出现在 wcfserviceLibrary.DLL 中。

[DataContract]
public class memberdesignations
{
    [DataMember]
    public string DesigId
    {
        get { return DesigId; }
        set { DesigId = value;}
    }
    [DataMember]
    public string DesignationName
    {
        get { return DesignationName; }
        set { DesignationName = value; }
    }

}

然后我有一个名为Type memberdesignations的方法,代码如下:

public List<memberdesignations> memberdesignations()
    {
        List<memberdesignations> designations = new List<memberdesignations>();
        memberdesignations objmemDesignations;
        ds = objbll.Get_Member_Designations();
        DataView dv = new DataView();
        dv = ds.Tables[0].DefaultView;
        foreach (DataRowView drow in dv)
        {
            objmemDesignations = new memberdesignations();
            objmemDesignations.DesigId = drow["DesignationId"].ToString();
            objmemDesignations.DesignationName = drow["DesignationName"].ToString();
            designations.Add(objmemDesignations);
        }
        return designations;
    }

我在包含get set属性的类中遇到了错误。

但是当我像这样修改类时,我能够摆脱错误:

 [DataContract]
public class memberdesignations
{
    [DataMember]
    public string DesigId
    {
        get;  set;
    }
    [DataMember]
    public string DesignationName
    {
        get; set;
    }
}

在搜索论坛时,我发现Konamiman在这里解释了它的原因。

我想知道Konamiman所解释的属性两种不同方式之间的区别,或者其他任何解释都可以。

谢谢。

3个回答

43

问题在于,正如Konamiman所说,您正在递归调用属性。

假设我有一个字符串属性“DesignationName”。

public string DesignationName
{
  //Some getter to return some data
  //Some setter to set the data
}

你期望它返回什么?那就返回一个硬编码的字符串_designationName吧;

private string _designationName = "someName";
public string DesignationName
{
  get {return _designationName;}
  //Some setter to set the data
}

那可以起作用。但是,如果我让它返回自己会发生什么?

public string DesignationName
{
  get {return DesignatioName;}
  //Some setter to set the data
}

好的,它会一直调用DesignationName,然后又会再次调用自身,之后会再次调用DesignationName......如此循环,这会将数据压入堆栈,并一直进行下去,直到超出分配给堆栈的空间。就这样,一个stackoverflow(栈溢出)发生了。

你最后一个示例能够工作的原因是它使用了称为“自动属性”的新功能,该功能在.NET 3.0中推出。基本上,在幕后,它会为您的属性创建支持字段,使得这个:

public string DesignationName
{
  get;
  set;
}

实际编译后的行为就像这样:

private string _designationName = string.Empty;
public string DesignationName
{
  get { return _designationName; }
  set { _designationName = value; }
}

自动实现属性是 C# 3.0 的一个特性 :) - Bryan Crosby
在参考了这里发布的所有答案之后,我访问了MSDN文章,其中详细解释了属性。请访问此链接here - Mourya
是的,但了解幕后发生的事情很重要。比如说,如果你使用 List<int> 作为返回类型,那么知道 get;set; 不会自动初始化这个列表就很重要。因此,如果你忘记在构造函数中初始化它(调用 new List<int>()),它将返回一个空引用异常。 - Killnine
如果是这种情况,我更愿意使用私有和公共属性的组合来明确地进行操作,而不是让编译器自己处理。 - Mourya
这永远不会过时 :) 感谢您的回答,我刚刚犯了与 OP 相同的错误。 - Alexus
显示剩余3条评论

7
你在setter中引用了属性本身,这将导致递归调用。(一遍又一遍,直到堆栈溢出)
通过使用只有get;和set;的简写符号,你基本上添加了一个隐含的后备字段(类似于后备变量)。这样做的好处是,你不会触发递归调用,因为你的属性只是一个包装器,用来包装后备字段。

谢谢您的解释,现在我明白了错误的主要原因。 - Mourya

5

声明两个私有变量:_desigId、_designationName。您处于一个无限递归循环中。返回私有变量而不是属性。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接