C# - 如何使用LINQ to Objects创建不可变对象

时间:2014-08-31 09:44:31

标签: c# xml linq immutability

我通过解析XDocument中的值来创建LINQ对象。我的理解是,除非你真的需要稍后更改值,否则应该创建对象是不可变的,所以我已经创建了私有的setter。

public class GeoLookupResult
{
    public string LocationType { get; private set; }
    public string Country { get; private set; }
    public string CountryIso3166 { get; private set; }

    public GeoLookupResult(string locationType, string country, string countryIso3166)
    {
        this.LocationType = locationType;
        this.Country = country;
        this.CountryIso3166 = countryIso3166;
    }
}

但是,似乎我不能使用LINQ to Objects来创建一个像这样的构造函数的对象(因为" GeoLookupResult不包含' locationType的定义'"等):

XDocument document;

document = XDocument.Load("http://api.wunderground.com/api/d36f54198ebbb48c/geolookup/q/England/London.xml");

var query = from i in document.Descendants("response")
select new GeoLookupResult
{
    locationType = (string)i.Element("location").Element("type"),
    country = (string)i.Element("location").Element("country"),
    countryIso3166 = (string)i.Element("location").Element("country_iso3166")
};

有没有办法可以像这样使用构造函数?或者我应该抓住不变性的想法,只是拥有公共属性设置器并在LINQ查询中使用它们? (EG:LocationType = (string)i.Element("location").Element("type")

3 个答案:

答案 0 :(得分:3)

我不确定我的问题是否正确,但你试过这个吗?

var query = from i in document.Descendants("response")
                select new GeoLookupResult(
                    (string)i.Element("location").Element("type"),
                    (string)i.Element("location").Element("country"),
                     (string)i.Element("country_iso3166")
                );

这样,您将使用三个参数调用GeoLookupResult类的已定义构造函数。你现在拥有它的方式是,它试图调用默认构造函数,然后通过你声明为私有的setter来分配提供的属性。

答案 1 :(得分:2)

当然你可以使用自己的构造函数。在您的linq select语句中,您使用的Object Initializer名为new GeoLookupResult{..}。它主要用于您不想使用构造函数强制对象初始化对象时。

所以你应该调用自己的构造函数来代替Object Initializer

var query = from i in document.Descendants("response")
select new GeoLookupResult( 
    (string)i.Element("location").Element("type"),
    (string)i.Element("location").Element("country"),
    (string)i.Element("country_iso3166")
);

答案 2 :(得分:2)

作为构造函数提到的不是OOP构造函数,而是一个对象初始化机制(C#编译器语法糖),它有助于填充对象的公共属性和字段。 如果你坚持让你的对象保持不变,你应该使用构造函数/工厂方法让其他组件创建你的对象。