简体   繁体   English

C#匿名类型成员中是否可以使用别名?

[英]Is aliasing possible in C# anonymous type members?

I am developing a tool to automate some tasks on MSProject using .NET and the Office.MSProject.Interop library. 我正在开发一种工具,用于使用.NET和Office.MSProject.Interop库自动执行MSProject上的某些任务。

Suppose I have something like that: 假设我有这样的事情:

Project actvProject;
var taskInfoDic = actvProject.Tasks.Cast<Task>().Select(
            task => new
            {
                task.Guid,
                task.Name,
                task.Work,
                task.ActualWork,
                task.PercentWorkComplete,
                task.Start,
                task.Finish,
                task.Duration,
                task.Deadline
            }).ToDictionary(x => x.Guid);

 // More code that mutates actvProject and its Task members

Is it possible for the taskInfoDic values (which are made of members of a member of the actvProject object) to be changed if I mutate actvProject ? 是否有可能用于taskInfoDic值(其由所述的一个成员的成员actvProject对象),如果我突变改变actvProject

Shouldn't an anonymous type value be immutable ?? 匿名类型值不应该是不可变的吗?

You can mutate the dictionary , as dictionaries are mutable. 您可以对字典进行突变,因为字典是可变的。 This means you can add an entirely new key/value pair, or change the value associated with a key. 这意味着您可以添加全新的键/值对,或更改与键关联的值。 You can't mutate the existing value object that some key points to (in this case, because the dictionaries value is an immutable type). 您不能更改某些键指向的现有值对象(在这种情况下,因为字典值是不可变的类型)。

You are also copying all of the data out of the original data source when creating the dictionary, you are not copying references to any of the values, or deferring execution in any way, so there are no changes that could be made to the source data structure that could be observed in the new dictionary. 创建字典时,您还将所有数据从原始数据源中复制出来,而不是复制对任何值的引用或以任何方式推迟执行,因此无法对源数据进行任何更改。新字典中可以观察到的结构。

Shouldn't a anonymous type value be immutable? 匿名类型值不应该是不可变的吗?

They are. 他们是。 That doesn't mean that any data structure you put them in is also immutable though. 但这并不意味着您放入它们的任何数据结构也是不可变的。

You could use an IReadOnlyDictionary if you want to ensure the dictionary isn't mutated, but given the fact that you're using an anonymous type, you shouldn't be using this dictionary outside of the scope of the current method; 如果要确保字典不发生突变,可以使用IReadOnlyDictionary ,但是鉴于您使用的是匿名类型,因此不应在当前方法的范围之外使用此字典。 given that, you really shouldn't need to go to such lengths to prevent mutation of the dictionary, as you are the only one who should be able to mutate it. 鉴于此,您真的不需要花那么长时间来防止字典的突变,因为您是唯一应该能够对其进行突变的人。

Is it possible for the taskInfoDic values (which are made of members of a member of the actvProject object) to be changed if I mutate actvProject ? 是否有可能用于taskInfoDic值(其由所述的一个成员的成员actvProject对象),如果我突变改变actvProject

No, because all of the members you pull out are value types . 不,因为您拉出的所有成员都是值类型 If any had been reference types than all you have is a reference, and changes to the underlying instances would be reflected in the results of your query. 如果引用类型比您拥有的所有引用类型多,则对基础实例的更改将反映在查询结果中。

Shouldn't a anonymous type value be immutable ?? 匿名类型值不应该是不可变的吗?

Yes they should, and they are . 是的,他们应该,而且 However, you are creating a dictionary where the anonymous type is the value . 但是,您正在创建一个匿名类型为value字典 Dictionaries are mutable, but the values (in this case) are not. 字典是可变的,但值(在这种情况下)不是可变的。

Here's a rough example that shows once you populate an anonymous type, it's data cannot be changed implicitly: 这是一个粗略的示例,显示了一旦您填充匿名类型,就无法隐式更改其数据:

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    static void Main(string[] args)
    {
        var actvProject = new Project();

        var taskInfoDic = actvProject.Tasks.Cast<Task>().Select(
        task => new
        {
            task.Guid,
            task.Name
        }).ToDictionary(x => x.Guid);

        actvProject.Tasks[0].Name = "New Task";

        foreach (var t in taskInfoDic)
        {
            Console.WriteLine(t.Value.Name);    // Still "Task 1"
        }

        // This won't compile as "Name" is readonly.
        // taskInfoDic.ElementAt(0).Value.Name = "test";
    }
}

public class Project
{
    public Project()
    {
        Tasks = new List<Task> { new Task { Name = "Task 1" } };
    }

    public IList<Task> Tasks { get; set; }
}

public class Task
{
    public Guid Guid { get; set; }

    public string Name { get; set; }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM