更改从 linq 查询接收的项属性

本文关键字:属性 查询 linq | 更新日期: 2023-09-27 18:35:08

我需要更改查询返回的列表项的值...它一定很简单,但我无法使用 linq 看到它。

该列表由以下结构的元素组成:

public struct HeaderButton
    {
        public string content {get; set;}
        public BitmapImage icon {get; set;}
        public PageContainerFactory.ContainerType containerType {get; set;}
        public bool IsSelected { get; set; }
    }
private List<HeaderButton> _headerButtons;
public List<HeaderButton> HeaderButtons
    {
        get
        {
            if (_headerButtons == null)
                _headerButtons = new List<HeaderButton>();
            return _headerButtons;
        }
        set { _headerButtons = value; }
    }

我试过这个:

HeaderButtons.First(x => x.containerType == CurrentContainer.CType).IsSelected = true;

编译器告诉我:

无法修改"System.Linq.Enumerable.First(System.Collections.Generic.IEnumerable, System.Func)"的返回值,因为它不是变量

现在我正在尝试的查询:

var h = HeaderButtons.First(x => x.containerType == CurrentContainer.CType);
h.IsSelected = true;

由于编译器错误,我不得不在 var 中获取元素。按照上面的代码来做,显然"h"并不指向"HeaderButtons"真正的元素,因为它是一个新的HeaderButton对象而不是引用。

更改从 linq 查询接收的项属性

根据您的评论,我决定创建一个嵌套类来代替结构,因为这种对象不在内容类之外使用,现在这是一个类(对象引用)而不是结构(值),一切正常。

代码:

sealed class MainViewModel : ViewModelNavigator
{
    internal class HeaderButton
    {
        public string Content { get; set; }
        public BitmapImage Icon { get; set; }
        public PageContainerFactory.ContainerType ContainerType { get; set; }
        public bool IsSelected { get; set; }
    }

private List<HeaderButton> _headerButtons;
public List<HeaderButton> HeaderButtons
    {
        get
        {
            if (_headerButtons == null)
                _headerButtons = new List<HeaderButton>();
            return _headerButtons;
        }
        set { _headerButtons = value; }
    }

HeaderButtons.First(x => x.ContainerType == CurrentContainer.CType).IsSelected = true;

编译器正在拯救您免于搬起石头砸自己的脚。

因为 HeaderButton 是一个结构,所以它是按值而不是按引用传递的。这意味着 Linq First 运算符正在作用于(并将返回)列表中元素的值副本。

因为 First 的返回值没有分配给任何临时的,并且在语句末尾会超出范围,而且由于它是一个值副本而不是对列表中项的引用,因此您对它所做的任何更改都不会影响列表中的项。

如果要编译,您可能很容易被误导,认为您已经更新了列表中的项目,而您不会这样做。通过拒绝编译编译器,您不必跟踪可能是一个棘手的错误。

如果您有理由将 HeaderButton 保留为结构,那么像这样的语句将使您能够更新它。

var hb = HeaderButtons.First(x => x.containerType == CurrentContainer.CType);
HeaderButtons[HeaderButtons.IndexOf(hb)].IsSelected = true;

如果你走这条路,你需要确保你的结构的相等操作以对你有用的方式运行,这取决于与"如果你有理由保留 HeaderButton 作为结构"相同的因素,因为想要使用结构而不是类的部分意味着想要值相等而不是引用相等语义。