如何按值将项目列表中的项目分配给新对象?

时间:2017-04-03 15:52:11

标签: c# list

在我的应用程序中,我有一个' PortalItemTag'对象。 PortalItemTag将Portal,Item和Tag关联在一起。我被要求获取属于每个PortalItemTag对象的PortalItemTagTypeId,并将该值复制到Tag对象上的PortalItemTagTypeId属性。

作为参考,PortalItemTag对象由Portal对象,Item对象,Tag对象和一些其他属性组成。

当我将每个属性分配给Tag时,我意识到我的标签列表是通过引用分配给PortalItems的。 foreach循环中的第一行代码执行此操作。

我没有创建对Tag对象的引用,而是喜欢分配Tag对象的新实例。是否有捷径可寻?

        foreach (var portalItemTag in portalItemTags)
        {
            var tag = _tags.FirstOrDefault(_ => _.Id == portalItemTag.TagId);

            portalItemTag.Tag = tag; 

            if (portalItemTag.Tag != null)
                portalItemTag.Tag.PortalItemTagTypeId = portalItemTag.PortalItemTagTypeId;
        }

退出上述循环后,我希望看到两个记录具有相同的标记,但PortalItemTagTypeId不同。

PortalItemTag - Object 1
PortalId: 1
ItemId: 1
PortalItemTagTypeId: 1
Tag:
{
Id:1
Name: Sample Tag
PortalItemTagTypeId:1
}

PortalItemTag - Object 2
PortalId: 1
ItemId: 1
PortalItemTagTypeId: 2
Tag:
{
Id:1
Name: Sample Tag
PortalItemTagTypeId:2
}

但是,目前最后一次分配获胜是因为我引用了Tag对象并在引用的对象上更改了PortalItemTagTypeId,这对于两个PortalItemTags都改变了它。

有没有人想过如何在没有太多痛苦的情况下实现这一目标?我试图避免实施克隆()'方法但如果它是唯一的方法就会这样做......

提前致谢!

为清晰起见,编辑了样本对象。

1 个答案:

答案 0 :(得分:1)

您希望更新portalItemTag.PortalItemTagTypeId并为Tag对象添加具有相同值的新portalItemTag吗?

这应该有效:

foreach (var portalItemTag in portalItemTags)
{
    // Get the tag that matches this portalItemTag.TagId
    var tag = _tags.FirstOrDefault(_ => _.Id == portalItemTag.TagId);

    // If it's not null, copy the tag to this object 
    // and update it's PortalItemTagTypeId property
    if (tag != null)
    {
        // Create a new tag and copy the property values from the other tag to this one
        var newTag = new Tag
            {
                Id = tag.Id,
                Name = tag.Name,
                PortalItemTagTypeId = tag.PortalItemTagTypeId 
            };

        portalItemTag.PortalItemTagTypeId = tag.PortalItemTagTypeId;
        portalItemTag.Tag = newTag;
    }
}

如果您在不同的地方执行此操作,或者Tag对象的属性可能会更改,则可能需要在Clone类本身上实现Tag方法。它看起来像是:

class Tag
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int PortalItemTagTypeId { get; set; }

    public Tag Clone()
    {
        return new Tag { Id = Id, Name = Name, 
            PortalItemTagTypeId = PortalItemTagTypeId };
    }
}

然后您的foreach代码将简化为:

foreach (var portalItemTag in portalItemTags)
{
    var tag = _tags.FirstOrDefault(_ => _.Id == portalItemTag.TagId);

    if (tag != null)
    {
        portalItemTag.PortalItemTagTypeId = tag.PortalItemTagTypeId;
        portalItemTag.Tag = tag.Clone();
    }
}

您在评论中提到您希望在一行中完成此操作。虽然它可能很有趣并且看起来很酷,但如果出现问题,其他人阅读或调试会很痛苦,但这是你可以做到的一种方法(使用上面描述的Clone方法)。请注意,在这个混乱中有两个分配,第二个分配基于第一个的结果。但一眼就看起来只发生了一次任务:

foreach (var portalItemTag in portalItemTags)
{
    portalItemTag.PortalItemTagTypeId =
        (portalItemTag.Tag = _tags.Any(t => t.Id == portalItemTag.TagId)
            ? _tags.First(t => t.Id == portalItemTag.TagId).Clone()
            : default(Tag)) != default(Tag)
                ? portalItemTag.Tag.PortalItemTagTypeId
                : portalItemTag.PortalItemTagTypeId;
}