也许这真的很简单或违反了所有规则,或者我只是不知道它叫什么,所以我找不到它。
无论如何,我希望能够替换堆上的整个对象。我添加了一个小代码示例,以显示我想要做的事情,以及一种方法,但我只是想知道是否有更优雅的方式?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BasicObjectTest
{
class Program
{
static void Main(string[] args)
{
List<Test> testList = new List<Test>
{
new Test {Value=1,NiceString="First" },
new Test {Value=2,NiceString="Second" },
new Test {Value=3,NiceString="Third" }
};
var replacementTestClass = new Test { Value = 2, NiceString = "NEW" };
EasyWay(testList, replacementTestClass);
var correctTestClass = testList.FirstOrDefault(x => x.Value == 2);
Console.WriteLine(correctTestClass.NiceString); //Expecting "Forth"
Console.ReadLine();
HardWay(testList, replacementTestClass);
correctTestClass = testList.FirstOrDefault(x => x.Value == 2);
Console.WriteLine(correctTestClass.NiceString);
Console.ReadLine();
}
private static void HardWay(List<Test> testList, Test replacementTestClass)
{
//This will work!
var secondTestClass = testList.FirstOrDefault(x => x.Value == 2);
CopyPropertiesUsingPropertyInfo(secondTestClass, replacementTestClass);
}
private static void CopyPropertiesUsingPropertyInfo(Test secondTestClass, Test replacementTestClass)
{
foreach(var pi in secondTestClass.GetType().GetProperties())
{
pi.SetValue(secondTestClass, pi.GetValue(replacementTestClass, null));
}
}
private static void EasyWay(List<Test> testList, Test replacementTestClass)
{
//This wont work, but I want it to!
var secondTestClass = testList.FirstOrDefault(x => x.Value == 2);
secondTestClass = replacementTestClass;
}
}
}
和我的测试对象
class Test
{
public int Value { get; set; }
public string NiceString { get; set; }
}
必须有一种更优雅的方式吗? 我知道为什么第一个替代方法不起作用:我只是更改该变量的对象引用。
更新: 使用这种思路我已经理解了很长一段时间,我现在测试它,认为它会起作用,但是测试失败了。为什么?我没有替换对象,以便使用它的每个对象都应该使用新对象吗?请参阅下面的完整代码
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var main = new Main { Property = 1 };
var dependent = new Dependent(main);
void ChangeRef(ref Main Oldmain, Main newMain)
{
Oldmain = newMain;
}
ChangeRef(ref main, new Main { Property = 5 });
Assert.AreEqual(5,dependent.Main.Property);
}
}
public class Main
{
public int Property { get; set; }
}
public class Dependent
{
public Dependent(Main main)
{
Main = main;
}
public Main Main { get; set; }
}
答案 0 :(得分:2)
必须有一种更优雅的方式吗?
你遗失了一件基本的东西。当您在列表中搜索对象时,如果找到一个对象,则会返回指向该对象的副本。这意味着当你改变它时,你只是在改变副本。列表中的原始引用仍然指向同一个旧对象实例。
但如果我没有列表怎么办?我只是在一个对象引用 变量?
然后您可以使用ref
keyword通过引用传递引用类型:
final String PRE_HTML = "<html><p style=\"text-align: left; width: 230px\">";
final String POST_HTML = "</p></html>";
tabbedpane.setTitleAt(0, PRE_HTML + "your title" + POST_HTML);
tabbedpane.setTitleAt(2, PRE_HTML + "your title 2" + POST_HTML);
答案 1 :(得分:0)
另一种解决方法是使用谚语&#34;额外的间接水平&#34;。
而不是将对象存储在列表中,而是存储包装器对象。包装器对象提供了一个&#34; Item&#34;指向实际对象的字段。然后你可以更新&#34;项目&#34;字段将其指向新对象。
一个简单的通用包装类可能如下所示:
class Wrapper<T>
{
public T Item;
public Wrapper(T item)
{
Item = item;
}
public static implicit operator Wrapper<T>(T item)
{
return new Wrapper<T>(item);
}
}
然后你可以像这样使用它:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication2
{
class Test
{
public int Value { get; set; }
public string NiceString { get; set; }
}
class Wrapper<T>
{
public T Item;
public Wrapper(T item)
{
Item = item;
}
public static implicit operator Wrapper<T>(T item)
{
return new Wrapper<T>(item);
}
}
class Program
{
static void Main(string[] args)
{
var testList = new List<Wrapper<Test>>
{
new Test {Value = 1, NiceString = "First"},
new Test {Value = 2, NiceString = "Second"},
new Test {Value = 3, NiceString = "Third"}
};
var replacementTestClass = new Test { Value = 2, NiceString = "NEW" };
EasyWay(testList, replacementTestClass);
var correctTestClass = testList.FirstOrDefault(x => x.Item.Value == 2);
Console.WriteLine(correctTestClass.Item.NiceString); //Expecting "New"
Console.ReadLine();
}
private static void EasyWay(List<Wrapper<Test>> testList, Test replacementTestClass)
{
var secondTestClass = testList.FirstOrDefault(x => x.Item.Value == 2);
secondTestClass.Item = replacementTestClass;
}
}
}