List.First()是否返回一个新实例?

时间:2015-04-10 06:43:02

标签: c# linq

我发现的行为与我对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

Initial GroupIndex of selected list item is -1

在GroupIndex值更改后从上面的代码测试参数值,因为您可以看到它更改为1

test parameter value from code above after GroupIndex value changing - as you can see it changed to 1

运行上述代码后所选列表项的值=&gt;还是-1

Value of selected list item after run the code above - still -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();
}

谢谢

3 个答案:

答案 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类吗?