Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在使用函数调用时,C#6.0默认属性值是如何分配的,以及如何受作用域的影响?_C#_Garbage Collection_C# 6.0 - Fatal编程技术网

在使用函数调用时,C#6.0默认属性值是如何分配的,以及如何受作用域的影响?

在使用函数调用时,C#6.0默认属性值是如何分配的,以及如何受作用域的影响?,c#,garbage-collection,c#-6.0,C#,Garbage Collection,C# 6.0,我可能会在这里得到一些反对票,但实际上,我通过正常搜索发现了相互冲突的信息,希望得到其他人也能轻松找到的明确答案 给定当前C#中的属性: 我的想法是,它的功能如下: if(foo == null) { foo = GetMyStrings();} 并且该foo将在对象的生存期内保留其第一次运行的GetMyStrings()的值,除非被手动指定的值覆盖 我的同事坚持认为这可能会导致GC问题,并且GetMyStrings()的结果可能会超出范围并被收集,“重新调用”参数,并导致在对象的生命周期内多

我可能会在这里得到一些反对票,但实际上,我通过正常搜索发现了相互冲突的信息,希望得到其他人也能轻松找到的明确答案

给定当前C#中的属性:

我的想法是,它的功能如下:

if(foo == null) { foo = GetMyStrings();}
并且该foo将在对象的生存期内保留其第一次运行的
GetMyStrings()
的值,除非被手动指定的值覆盖

我的同事坚持认为这可能会导致GC问题,并且
GetMyStrings()
的结果可能会超出范围并被收集,“重新调用”参数,并导致在对象的生命周期内多次调用
GetMyStrings()


我们谁是对的

不,实际上是这样的:

static ClassName()
{
    foo = GetMyStrings();
}
static MyClass() {
    Foo = GetMyStrings();
}
编译器生成一个静态构造函数并将赋值调用放入其中(就像它在构造函数中为非静态属性创建一行一样)

我的同事坚持认为这可能会导致GC问题,并且GetMyString()的结果可能会超出范围并被收集,“重新调用”参数,并导致在对象的生命周期内多次调用GetMyString()

他在胡说八道。分配的实例将永远不会被垃圾收集,无论它是从何处分配的。

写这篇文章

public static IEnumerable<string> Foo { get; set; } = GetMyStrings();
(如果您已经有一个静态构造函数,
Foo=GetMyStrings();
line被隐式添加到它)

除此之外,没有区别:,
GetMyStrings()
从构造函数调用,然后将其返回的值分配给
Foo
。之后,该值将一直保留,直到被另一个值替换,或者程序结束

就“重新生成”参数而言,它永远不会发生在类对象的同一个实例上。卸载包含该类的应用程序域或将该类加载到另一个应用程序域时,可以多次调用
GetMyStrings()
,但这与新的C#6语法无关

最后,如果您不打算在静态构造函数之后更改<代码> Foo,考虑将其设为只读:

public static IEnumerable<string> Foo { get; } = GetMyStrings();
public静态IEnumerable Foo{get;}=getMyString();

要举例说明我的评论,请看以下示例:

public void RunTest()
{
    Test t = new Stackoverflow.Form1.Test();
    Console.WriteLine(t.Values.First());
    System.Threading.Thread.Sleep(1000);
    Console.WriteLine(t.Values.First());
    System.Threading.Thread.Sleep(1000);
    Console.WriteLine(t.Values.First());

    Console.WriteLine("------");
    Console.WriteLine(t.Values2.First());
    System.Threading.Thread.Sleep(1000);
    Console.WriteLine(t.Values2.First());
    System.Threading.Thread.Sleep(1000);
    Console.WriteLine(t.Values2.First());

    Console.WriteLine("------");
    Console.WriteLine(t.Values3.First());
    System.Threading.Thread.Sleep(1000);
    Console.WriteLine(t.Values3.First());
    System.Threading.Thread.Sleep(1000);
    Console.WriteLine(t.Values3.First());
}

public class Test
{
    public IEnumerable<string> Values { get; set; } = GetValues();

    public static IEnumerable<string> GetValues()
    {
        List<string> results = new List<string>();
        for (int i = 0; i < 10; ++i)
        {
            yield return DateTime.UtcNow.AddMinutes(i).ToString();
        }
    }

    public IEnumerable<string> Values2 { get; set; } = GetValues2();

    public static IEnumerable<string> GetValues2()
    {
        return GetValues().ToList();
    }

    public IEnumerable<string> Values3 { get; set; } = GetValues().ToList();
}
值:如您所见,使用yield的方法中的IEnumerable将在每次调用时进行求值

Values2:该方法返回一个列表。由于List实现了IEmnumerable,所以您仍然只返回List的具体实例(尽管它是作为IEnumerable接口显示的),因此它只得到一次计算

Values3:我们基本上将.ToList()移到GetValues2()方法之外,并直接在属性上实现它。这里的结果与值2相同,原因基本相同

当您返回实现IEnumerable的具体对象时,将对其求值一次,但请注意第一个示例

大家记住,Linq是一种观点。如果基础数据发生更改,那么从Linq表达式返回的内容也会发生更改



关于垃圾收集问题:被活动对象引用的对象将不会被垃圾收集。

你能给IEnumerable分配一个字符串吗?这是我对示例的错误回答,因为coffee==null。正在修复。请更正您的示例,使其至少可编译?已将示例修复为实际有意义的内容。如果您使用事物的专有名称,可能会有所帮助。它们不是默认值,它们是初始值设定项。这就足够了,对吗?“静态”实例永远不会被删除,因此分配的静态成员不会被删除。谢谢。同一位同事曾经告诉我,他不使用Linq,因为它“还没有出现足够长的时间”。3年前。我今天免费吃午餐。LINQ是在2007年随C#3发布的。它已经有10年的历史了。对于大多数已经处于生命周期末期的技术;)@CDove@CDove什么!?!曾经有过这样的同事,他们发誓任何比他们最了解自己的手艺自动成为魔鬼魔法的程度还要新的东西吗?我赢了很多赌注。。。
static MyClass() {
    Foo = GetMyStrings();
}
public static IEnumerable<string> Foo { get; } = GetMyStrings();
public void RunTest()
{
    Test t = new Stackoverflow.Form1.Test();
    Console.WriteLine(t.Values.First());
    System.Threading.Thread.Sleep(1000);
    Console.WriteLine(t.Values.First());
    System.Threading.Thread.Sleep(1000);
    Console.WriteLine(t.Values.First());

    Console.WriteLine("------");
    Console.WriteLine(t.Values2.First());
    System.Threading.Thread.Sleep(1000);
    Console.WriteLine(t.Values2.First());
    System.Threading.Thread.Sleep(1000);
    Console.WriteLine(t.Values2.First());

    Console.WriteLine("------");
    Console.WriteLine(t.Values3.First());
    System.Threading.Thread.Sleep(1000);
    Console.WriteLine(t.Values3.First());
    System.Threading.Thread.Sleep(1000);
    Console.WriteLine(t.Values3.First());
}

public class Test
{
    public IEnumerable<string> Values { get; set; } = GetValues();

    public static IEnumerable<string> GetValues()
    {
        List<string> results = new List<string>();
        for (int i = 0; i < 10; ++i)
        {
            yield return DateTime.UtcNow.AddMinutes(i).ToString();
        }
    }

    public IEnumerable<string> Values2 { get; set; } = GetValues2();

    public static IEnumerable<string> GetValues2()
    {
        return GetValues().ToList();
    }

    public IEnumerable<string> Values3 { get; set; } = GetValues().ToList();
}
19/04/2017 12:24:25
19/04/2017 12:24:26
19/04/2017 12:24:27
------
19/04/2017 12:24:25
19/04/2017 12:24:25
19/04/2017 12:24:25
------
19/04/2017 12:24:25
19/04/2017 12:24:25
19/04/2017 12:24:25