C# setter 中的堆栈溢出异常

Posted

技术标签:

【中文标题】C# setter 中的堆栈溢出异常【英文标题】:Stack overflow exception in C# setter 【发布时间】:2011-03-17 14:40:03 【问题描述】:

这行得通:

using System;
using ConstraintSet = System.Collections.Generic.Dictionary<System.String, double>;

namespace ConsoleApplication2

    class test
    
        public ConstraintSet a  get; set; 
        public test()
        
            a = new ConstraintSet();
        
        static void Main(string[] args)
        
            test abc = new test();
            Console.WriteLine("done");
        
    

这不是:

using System;
using ConstraintSet = System.Collections.Generic.Dictionary<System.String, double>;

namespace ConsoleApplication2

    class test
    
        public ConstraintSet a  get  return a;  set  a = value;  
        public test()
        
            a = new ConstraintSet();
        
        static void Main(string[] args)
        
            test abc = new test();
            Console.WriteLine("done");
        
    

我在第二类的 a 的 setter 上遇到堆栈溢出异常,我不知道为什么。我不能使用第一种形式,因为Unity game engine 不支持它。

【问题讨论】:

I cannot use the first form because it is not supported by unity engine ... 第一种形式是编译器级别的简写。它应该可以与统一引擎一起正常工作。 *** on class property 和许多其他的可能重复。 不,unity c# 编译器不支持这种语法 【参考方案1】:

当您编写a = value 时,您再次调用了属性设置器。

为了使用非自动属性,您需要创建一个单独的私有支持字段,如下所示:

ConstraintSet a;
public ConstraintSet A  get  return a;  set  a = value;  

【讨论】:

很有趣,这些年来这个过程没有改变。【参考方案2】:

你还没有声明一个支持变量——你只是有一个属性,它的 getter 和 setter 调用自己。我不清楚 为什么 Unity 不支持第一种形式 - 这意味着可能也不支持等效形式,但基本上是这样的:

private ConstraintSet aValue;
public ConstraintSet a  get  return aValue;  set  aValue = value;  

当然,我通常会有一个更传统的名字——这意味着你可以不用“值”位:

private ConstraintSet constraints;
public ConstraintSet Constraints

    get  return constraints;  
    set  constraints = value; 

要更详细地说明为什么您当前的第二种形式会抛出***Exception,您应该始终记住,属性基本上是伪装的方法。您的损坏代码如下所示:

public ConstraintSet get_a()

    return get_a();


public void set_a(ConstraintSet value)

    set_a(value);

希望很明显,为什么该版本会破坏堆栈。修改后的版本只是设置了一个变量而不是再次调用该属性,所以展开后是这样的:

private ConstraintSet aValue;

public ConstraintSet get_a()

    return aValue;


public void set_a(ConstraintSet value)

    aValue = value;

【讨论】:

只是unity c#编译器不支持visual c#的功能。这是因为它必须保持与单声道的兼容性 @Patrik:Mono 也支持 C# 3... C# 3 已经推出近 3 年了;这并不是一个新功能。 我猜这是因为 mac 兼容性。我不知道确切的原因,但统一编译器说 get 和 set must 有一个 body @Patrik:Mac 兼容性应该与它无关。如果他们打扰,他们可以轻松地支持它——它不需要任何新的框架或运行时特性。基本上听起来 Unity 编译器有点过时了:( @Dan:是什么让你认为有两个变量?没有——只有一个字段和一个属性可以访问它……就像在 Java 中你有一个字段和一两个方法来访问它一样。并且使用自动实现的属性,甚至隐藏字段声明。您在哪里看到两个变量?【参考方案3】:

您不能在 getter 和 setter 中使用相同的变量名。这将导致它调用自己并最终导致堆栈溢出。递归过多。

你需要一个支持变量:

private ConstraintSet _a;
public ConstraintSet a  get  return _a;  set  _a = value;  

【讨论】:

【参考方案4】:

您的公共属性中需要一个私有支持变量:

private ConstraintSet _a;
public ConstraintSet a  get  return _a;  set  _a = value;  

【讨论】:

以上是关于C# setter 中的堆栈溢出异常的主要内容,如果未能解决你的问题,请参考以下文章

C#:递归方法期间的堆栈溢出异常

堆栈溢出错误可为空的数字类型c#

为啥这个 BigInteger 值会导致堆栈溢出异常? C#

傻程序中的堆栈溢出异常

函数 堆栈溢出

怎么防止堆栈溢出