2013-12-23 52 views
0

我正在开发一个工具,使用.NET和Office.MSProject.Interop库自动执行MSProject上的一些任务。在C#匿名类型成员中是否可以使用别名?

假设我有类似的东西:

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改变?

不应该匿名类型的值是不可变的?

+3

匿名类型成员是只读的。你为什么不把它推广到适当的课堂?这将给你任何你想要的控制... –

回答

2

可以变异的字典,因为字典是可变的。这意味着您可以添加全新的键/值对,或更改与键关联的值。你不能改变现有值对象的某些关键点(在这种情况下,因为字典值是不可变的类型)。

您也在创建字典时复制了原始数据源中的所有数据,不复制对任何值的引用或以任何方式推迟执行,因此没有可以进行的更改到可以在新字典中观察到的源数据结构。

匿名类型值不应该是不可变的吗?

他们是。这并不意味着你放入它们的任何数据结构也是不可变的。

如果你想确保字典不被突变你可以使用一个IReadOnlyDictionary,但鉴于您使用的是匿名类型,你不应使用的范围之外的这本字典现行方法;考虑到这一点,你真的不需要为了防止字典的变化而花费这么长的时间,因为你是唯一能够改变它的人。

+0

我的关注是,当我在activProject上工作时,“任务”(在activProject对象中)属性被改变。我担心activProject中的这些更改是否能够将自己反映到字典的值中。 activProject是一个巨大的COM对象,当我完成我的工作时,会产生很多副作用。 现在我的理解是,我无法更改匿名对象内的引用值。但是如果被引用的对象改变它的状态,这个改变是否会反映在字典返回的值中? –

+0

我认为我没有完全正确的术语=( –

+0

@RananRanelli正如我在第二段中所述,在您创建的字典中不能更改源数据结构或其项目,或者它的项目,也就是说,除非你已经取出的'task'的属性是可变引用类型,否则你需要做一个更深层的副本。 – Servy

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; } 
} 
1

是否有可能用于taskInfoDic值(其由与actvProject对象的成员的成员),如果我突变actvProject改变?

不,因为您拉出的所有成员都是值类型。如果有任何引用类型比你所拥有的是一个引用,并且对底层实例的更改将反映在你的查询结果中。

不应该匿名类型的值是不可变的?

是的,他们应该,他们。但是,您正在创建字典,其中匿名类型是。字典是可变的,但值(在这种情况下)不是。

+0

我认为匿名类型是引用类型,而不是值类型 – Servy

+0

@Servy我指的是从原始'任务'列表中删除的字段 - 'Guid','Name'等。 –

相关问题