C# 通过扩展方法更新值而不返回

C# 通过扩展方法更新值而不返回,c#,extension-methods,C#,Extension Methods,现在我用这个, c1 = c1.AddItem(d1); public static T AddItem<T, TItem>(this T entity, TItem item) where T : BaseClass<T> { //somecode return entity; } 但我希望能够改变价值而不必回报 c1.AddItem(d1); public static void AddItem<T, TItem>(this T e

现在我用这个,

c1 = c1.AddItem(d1);

public static T AddItem<T, TItem>(this T entity, TItem item) where T : BaseClass<T>
{
    //somecode
    return entity; 
}
但我希望能够改变价值而不必回报

c1.AddItem(d1);

public static void AddItem<T, TItem>(this T entity, TItem item) where T : BaseClass<T>
{
    //somecode 
}
你知道怎么做吗

完整代码

public class C : BaseClass<C>
{
    public virtual int CId { get; set; }
    public virtual string Text { get; set; }
    public virtual IList<D> DList { get; set; }

    public C()
    {
        DList = new List<D>();
    }
}



    public static T AddItem<T, TItem>(this T entity, TItem item) where T : BaseClass<T>
    {
        var propertyList = item.GetType().GetProperties().ToList();

        var prop = propertyList.Find(c => c.PropertyType == typeof(T));

        if (propertyList.Any(c => c.PropertyType == typeof(T)))
        {
            propertyList.Find(c => c.PropertyType == typeof(T)).SetValue(item, entity);
        }
        else
        {
            ((IList<T>)propertyList.Find(c => c.PropertyType == typeof(IList<T>)).GetValue(item)).Add(entity);
        }

        var a = ((IList<TItem>)entity.GetType().GetProperties().ToList().Find(c => c.PropertyType == typeof(IList<TItem>)).GetValue(entity));
        if (a.GetType().Name == "PersistentGenericBag`1")
        {
            entity = entity.Load(x => (IList<TItem>)x.GetType().GetProperties().ToList().Find(c => c.PropertyType == typeof(IList<TItem>)).GetValue(x));
            a = ((IList<TItem>)entity.GetType().GetProperties().ToList().Find(c => c.PropertyType == typeof(IList<TItem>)).GetValue(entity));
        }

        a.Add(item);

        entity.Save();

        return entity;
    }


    public static T Load<T, TItem>(this T entity, Func<T, IList<TItem>> listGetter) where T : class
    {
        using (var session = NHibernateHelper<T>.OpenSession())
        {
            T reAttached = session.Merge<T>(entity);
            NHibernate.NHibernateUtil.Initialize(listGetter.Invoke(reAttached));

            return reAttached;
        }
    }

字符串是不可变的,对于其他类类型,代码应该可以工作

public class BaseClass<TItem>
{
    public BaseClass()
    {
        ItemList = new List<TItem>();
    }
    public List<TItem> ItemList { get; set; }
}

public static void AddItem<T, TItem>(this T entity, TItem item)
    where T :BaseClass<TItem>
{
    //somecode 
    entity.ItemList.Add(item);
}


public class TItem
{
    public string Name { get; set; }
}

static void Main(string[] args)
{
    BaseClass<TItem> myEntity = new BaseClass<TItem>();
    TItem newItem = new TItem();
    newItem.Name = "Hi";
    myEntity.AddItem(newItem);
}

您的问题似乎是由以下行引起的:

entity = entity.Load(x => (IList<TItem>)x.GetType().GetProperties().ToList().Find(c => c.PropertyType == typeof(IList<TItem>)).GetValue(x));
我对Hibernate的了解是有限的,但是很有可能,如果不是总是,至少有时,对Merge的调用将返回一个与传入的对象实例不同的对象实例的引用

这具有级联效应,即在扩展方法中,局部变量实体被重新分配给一个全新的对象。由于实体引用变量是c1引用变量的副本,而不是对其的引用,因此重新分配该变量时,更改不会反映在c1变量中。c1变量实际上仍然指向原始实体实例,直到调用BaseClass.Load对其进行更改

基本上,正如其他人已经指出的,要编写一个不需要返回实体引用的扩展方法,您必须限制自己通过实体对象的方法/属性来更改实体对象的状态。实际上不能完全更改对象引用,因为这永远不会反映在方法调用之外

在您的例子中,看起来您应该坚持使用返回实体引用的原始扩展方法

相关阅读:


特别是,本节旁注:通过引用传递值对象和通过值传递引用对象之间有什么区别?适用于此处发生的情况。

发生了什么?你能发布你在方法中使用的代码吗?你的示例代码只会让一切变得更加混乱。当然,不能更改字符串,它是不可变的。这个问题仅仅是关于不理解不可变对象是如何工作的吗?你能说明你想修改什么类型的对象吗?字符串是不可变的。。。但是您编写的代码应该可以与任何其他非值类型@blacai一起使用,@stann我添加了我的类too@sstan,他尝试更改传递的引用。这里没有不变性,我将研究合并部分。谢谢你的时间
T reAttached = session.Merge<T>(entity);
// ...
return reAttached;