关于 LINQ 和 Lambda 重新查询的问题
我对 LINQ 和 Lambda 查询的结果有疑问。 例如,我有以下代码:
class ClassA<T> {
public string Name { get; set; }
public T ObjectT { get; set; }
}
List<ClassA<T>> list;
// list is populated
// First way to get instance from list, reference type?
ClassA<T> instance1 = list.Select(x=> x).Where(x=>x.Name == "A").
FirstOrDefault();
// Second way to clone or copy instance from the list
ClassA<T> instance2 = list.Select(x=>
new ClassA<T> { Name = x.Name, ObjectT = x.ObjectT}).
Where( x=> x.Name = "A").FirstOrDefault();
显然,instance2 是列表中找到的实例的克隆或副本。 实例1怎么样? 这是一个新实例还是只是对列表中实例的引用? 如果instance1是对列表项的对象引用,则对其属性的任何更改都可能会更改列表中的同一对象。 是对的吗?
如果是这种情况,并且我不想对列表中的对象产生任何隐式影响,我认为我应该使用第二种策略。 但是,如果我确实希望检索到的实例中的任何更改也在列表中具有相同的更改,我应该使用策略 1。不确定我的理解是否正确。 任何意见?
I have a question about the result of LINQ and Lambda query. For example, I have the following codes:
class ClassA<T> {
public string Name { get; set; }
public T ObjectT { get; set; }
}
List<ClassA<T>> list;
// list is populated
// First way to get instance from list, reference type?
ClassA<T> instance1 = list.Select(x=> x).Where(x=>x.Name == "A").
FirstOrDefault();
// Second way to clone or copy instance from the list
ClassA<T> instance2 = list.Select(x=>
new ClassA<T> { Name = x.Name, ObjectT = x.ObjectT}).
Where( x=> x.Name = "A").FirstOrDefault();
It is obviously that instance2 is a clone or copy of an instance found in list. How about instance1? Is this one a new instance or just a reference to an instance in the list? If instance1 is an object reference to list's item, any change to its property may change the same object in the list. Is that right?
If that's the case and I don't want to have any implicit effect on objects in the list, I think I should use the second strategy. However, if I do want any changes in the retrieved instances also have the same changes in the list, I should use strategy 1. Not sure if my understanding is correct. Any comments?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
它将是对列表中对象的引用。 您可以做的是使用 Clone() 函数创建一个副本,该函数返回重复的结果,导致代码
注意 Select(x => x) 是不必要的。 克隆将是一种扩展方法,类似于
it will be a reference to the object in the list. What you could do, is create a copy using a Clone() function that returns a duplicate resulting in the code
Note that Select(x => x) is unnecessary. Clone would be an extension method along the lines of
由于您的
ClassA
是一个class
(而不是struct
),因此instance1
是对同一类的引用列表
内的对象。关于策略,如果您不希望列表的用户能够弄乱列表元素,我建议使用以下替代方案:
Make
ClassA
a结构
。 这样,任何查询都将返回列表中元素的副本;使
ClassA
实现如下所示的IClonable
,并在传递给不可信代码之前克隆它。让
请注意,
ObjectT
属性可能是一个类。 因此,即使在克隆ClassA
对象之后,ObjectT
属性也将是对同一对象的引用,并且任何用户代码都可以修改它。 也许,您还需要克隆ObjectT
;正如建议的,您可以使用扩展方法来避免空引用问题。 正如您所看到的,该问题有多种解决方案。 您应该选择更适合您的具体问题的一种。
编辑1:添加了CloneableExt
Since your
ClassA<T>
is aclass
(not astruct
),instance1
is a reference to the same object that is inside thelist
.About the strategy, if you didn't want the users of your list to be able to mess around the list elements, I would suggest these alternatives:
Make
ClassA<T>
astruct
. This way any query will return copy of the elements in the list;Make
ClassA<T>
implementIClonable
like below, and clone it before passing to a untrustworthy code.Beware that the
ObjectT
property might be a class. So, even after you clone theClassA<T>
object, theObjectT
property will be a reference to the same object, and any user code will be able to modify it. Maybe, you'll need to cloneObjectT
too;As suggested, you could use an extension method to avoid null reference problems. As you can see, there are several solutions to the problem. You should choose the one that better fit to your specific problem.
EDIT 1: CloneableExt added
是的,第一个查询不会克隆列表中的对象,因此
instance
将引用list
中的实际对象。 第二个查询显式构造对象的克隆。Yes, the first query doesn't clone the objects in the list, so
instance
will reference the actual object fromlist
. The second query explicitly constructs a clone of the object.您在第二个示例中所做的是浅表复制,这是一个新实例,但其引用类型成员仍被引用。
为了正确地做到这一点,你应该实现 ICloneable:
然后
What you do in your second example is a shallow copy, that is a new Instance but with its refernce type members still refensced.
To do it properly you should implement ICloneable:
and then