我发现的行为与我对List.First()
的看法不同:
我构建了一个包含列表的测试应用程序
public abstract class GridTemplateModelBase : INotifyPropertyChanged, IDisposable
{
Public ObservableCollection<ColumnModel> Columns
{
get
{
return _columns;
}
protected set
{
_columns = value;
OnPropertyChanged();
}
}
}
ColumnModel
类包含名为GroupIndex
的属性。我想从Columns
列表中选择特定项目,并将GroupIndex
属性设置为另一个类,因此我使用了以下代码:
//choose the list item I want to change
var test = GridProfile.Columns.First(p => p.FieldName == item);
//Change GroupIndex value
test.GroupIndex = 1;
我希望这段代码能够改变列表项的GroupIndex
值,但似乎是`Columns.First()&#39;方法返回此列表项的副本。
请参阅以下图像:
所选列表项的初始GroupIndex为-1
在GroupIndex值更改后从上面的代码测试参数值,因为您可以看到它更改为1
运行上述代码后所选列表项的值=&gt;还是-1
如果List.First()
方法返回所选列表项的引用,我们必须查看该列表项的相同值以及上面代码中的test
参数,但令人惊讶的是情况并非如此。< / p>
是否有人可以解释Linq.First()
方法的确切运作方式?
希望我的问题很清楚
以下是ColumnModel
班级内容:
public class ColumnModel : INotifyPropertyChanged
{
/// <summary>
/// Initializes a new instance of the ColumnModel class.
/// </summary>
public ColumnModel()
{
AllowEdit = DefaultBoolean.True;
SortIndex = -1;
GroupIndex = -1;
}
private string _cellToolTip;
private int _sortIndex;
private ColumnSortOrder _sortOrdering;
private bool _isReadOnly;
private int _groupIndex;
private bool _isVisible;
private bool _fixedWidth;
private double _minWidth;
private double _width;
private EditSettingsHorizontalAlignment _cellContentAlighnment;
private ColumnProfile _profileTemplate;
private string _fieldHeader;
private string _fieldName;
private DefaultBoolean allowEdit;
// Specifies the name of a data source field to which the column is bound.
public string FieldName
{
get
{
return _fieldName;
}
set
{
_fieldName = value;
OnPropertyChanged();
}
}
public string FieldHeader
{
get
{
return _fieldHeader;
}
set
{
_fieldHeader = value;
OnPropertyChanged();
}
}
// Specifies the type of template to load
public ColumnProfile ProfileTemplate
{
get
{
return _profileTemplate;
}
set
{
_profileTemplate = value;
OnPropertyChanged();
}
}
public EditSettingsHorizontalAlignment CellContentAlighnment
{
get
{
return _cellContentAlighnment;
}
set
{
_cellContentAlighnment = value;
OnPropertyChanged();
}
}
public double Width
{
get
{
return _width;
}
set
{
_width = value;
OnPropertyChanged();
}
}
public double MinWidth
{
get
{
return _minWidth;
}
set
{
_minWidth = value;
OnPropertyChanged();
}
}
public bool FixedWidth
{
get
{
return _fixedWidth;
}
set
{
_fixedWidth = value;
OnPropertyChanged();
}
}
public bool IsVisible
{
get
{
return _isVisible;
}
set
{
_isVisible = value;
OnPropertyChanged();
}
}
public int GroupIndex
{
get
{
return _groupIndex;
}
set
{
_groupIndex = value;
OnPropertyChanged();
}
}
public bool IsReadOnly
{
get
{
return _isReadOnly;
}
set
{
_isReadOnly = value;
OnPropertyChanged();
}
}
public ColumnSortOrder SortOrdering
{
get
{
return _sortOrdering;
}
set
{
_sortOrdering = value;
OnPropertyChanged();
}
}
public DefaultBoolean AllowEdit
{
get { return allowEdit; }
set
{
allowEdit = value;
OnPropertyChanged();
}
}
public string CellToolTip
{
get
{
return _cellToolTip;
}
set
{
_cellToolTip = value;
OnPropertyChanged();
}
}
public int SortIndex
{
get
{
return _sortIndex;
}
set
{
_sortIndex = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
更新:
根据您的意见我理解List.First()
返回引用类型,可能我的代码包含一个问题,或者我的调试器可能返回错误的结果 - 将检查它。
以下是First
源代码(credit:@Enigmativity):
public static TSource First<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
if (source == null)
throw Error.ArgumentNull("source");
if (predicate == null)
throw Error.ArgumentNull("predicate");
foreach (TSource source1 in source)
{
if (predicate(source1))
return source1;
}
throw Error.NoMatch();
}
谢谢
答案 0 :(得分:2)
.First(x => ...)
反编译如下:
public static TSource First<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
if (source == null)
throw Error.ArgumentNull("source");
if (predicate == null)
throw Error.ArgumentNull("predicate");
foreach (TSource source1 in source)
{
if (predicate(source1))
return source1;
}
throw Error.NoMatch();
}
它显然返回了实际的实例(如果source
是引用类型)。
您的代码中必须发生其他事情。
答案 1 :(得分:2)
根据this问题和所选答案,它取决于对象的值/引用类型:
如果它们是类,则实例是相同的,但如果它们是结构/值类型则复制。
请注意在Visual Studio中看到的有关lambda表达式的信息,根据您使用的版本,调试可能无法100%正确实现。不确定这是不是这样。
答案 2 :(得分:1)
它返回指定序列中的第一个元素,而不是新实例。所以这是存储在集合中的原始对象。 https://msdn.microsoft.com/en-us/library/vstudio/bb291976(v=vs.100).aspx 你可以发布ColumnModel类吗?