我正在开发一个工具,使用.NET和Office.MSProject.Interop
库在MSProject上自动执行某些任务。
假设我有类似的东西:
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
如果我变异taskInfoDic
,是否可以更改actvProject
值(由actvProject
对象的成员组成)?
匿名类型值不应该是不可变的吗?
答案 0 :(得分:2)
您可以改变词典,因为词典是可变的。这意味着您可以添加全新的键/值对,或更改与键关联的值。您不能改变某些键指向的现有值对象(在这种情况下,因为词典值是不可变类型)。
您还在创建字典时复制原始数据源中的所有数据,您没有复制对任何值的引用,或以任何方式推迟执行,因此不会对其进行任何更改可以在新词典中观察到的源数据结构。
匿名类型值不应该是不可变的吗?
他们是。这并不意味着您放入的任何数据结构也是不可变的。
如果你想确保字典没有变异,你可以使用IReadOnlyDictionary
,但鉴于你使用的是匿名类型,你不应该使用这个字典超出了当前方法的范围;鉴于此,你真的不需要这么长时间来防止字典的变异,因为你是唯一应该能够改变字典的人。
答案 1 :(得分:1)
如果我变异
taskInfoDic
,是否可以更改actvProject
值(由actvProject
对象的成员组成)?
不,因为您提取的所有成员都是值类型。如果有任何引用类型,那么你所拥有的只是一个引用,对基础实例的更改将反映在查询结果中。
匿名类型值不应该是不可变的吗?
是的,他们应该,而且他们 。但是,您正在创建词典,其中匿名类型是值。字典是可变的,但值(在这种情况下)不是。
答案 2 :(得分:0)
这是一个粗略的例子,显示一旦填充了匿名类型,它的数据就无法隐式更改:
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; }
}