【问题标题】:What are the criteria for using a new memory location when initializing a variable?初始化变量时使用新内存位置的标准是什么?
【发布时间】:2014-01-27 04:08:23
【问题描述】:

我在编写新的单元测试时遇到了一些问题。我在代码示例中的 cmets 解释了我的具体问题:

KeyboardLayout layout
    = Engine.ParseLayout(Dimensions.Create(300, 300), "FooBar", provider);
var dweeb = layout.Layout.SelectMany(t => t);

//Parsed layout is not a mutant
Assert.IsTrue(!layout.IsMutant);

KeyboardLayout newLayout = StandardKeyboardMutations.MutateKeyboard(layout);

var newb = newLayout.Layout.SelectMany(t => t);

//I don't understand why this test fails. They should be stored in seperate memeory locations and therefore not equal by reference comparison.
//Unless of course saying var x = foo doesn't always provide a fresh memory location for the value of foo.
Assert.AreNotEqual(layout, newLayout);

这条线 Assert.AreNotEqual(layout, newLayout); 总是失败。

我不知道为什么我一直在做出这个假设(以 cmets 表示):声明一个变量总是将存储过程执行到一个新的内存位置。 (当前正在运行的程序未使用该程序)。

要清楚,问题是,在 c# 中, var x = foo; 是否总是使用新的内存单元?如果不是,使用一个的标准是什么?或者它总是将值的地址存储在 x 中?还是我错过了什么,我问了一个完全错误的问题来找出这里有什么问题?

这是我的第一次“官方”单元测试体验,提前致谢。

【问题讨论】:

  • 我在StandardKeyboardMutations 上找不到任何文档。你有参考吗?
  • 自定义类。如果你想看看它的实现,我必须想出一个不同的例子。
  • 答案可能在于它的实现。除非您已覆盖 KeyboardLayout.Equals,否则您将获得 ReferenceEquals 实现。这意味着 StandardKeyboardMutations.MutateKeyboard 以某种方式返回对 layout 相同的对象的引用 - 可能不是您想要的。

标签: c# variables reference equality


【解决方案1】:

您正在寻找Assert.AreSame,而不是Assert.AreEqual

Assert.AreSame() 断言检查参数是否引用相同的对象(您提到“相同的内存位置”),而Assert.AreEqual()(和分别为AreNotEqual())断言检查底层对象的相等性,即.,它会检查 a.Equals(b),即使 ab 引用不同的对象,它也可以成立。

【讨论】:

  • 这是很好的信息。但是,我使用了 Assert.AreNotSame();方法和断言仍然失败。这些必须引用同一个对象,即使我的示例代码让我不相信。
  • 如果它们仍然相同,那么StandardKeyboardMutations 可能会利用Flyweight pattern 来共享它发出的突变。如果您可以扩展问题以包括上述实现或其相关部分,那将是最好的。
【解决方案2】:

var x = foo;总是使用新的记忆单元?

是的,x 永远是新的记忆平静。但是,不一定是您认为的意思。

或者它可能总是在x 中存储value 的地址?

是的,如果value 类型是引用类型。例如

var x = new MyClass();
var y = x;

xy 都包含对同一内存空间的引用(您可以将其视为地址),MyClass() 实例实际上存储在该内存空间中。

对于值类型,情况完全不同:

var x = new MyStruct();
var y = x;

整个对象在分配给y 时被复制。没有引用,对象本身存放在y中。

【讨论】:

  • 我怀疑 OP 实际上还需要其他东西。但是好的开始:) 优化和各种别名,其中 2 个变量共享内存位置,装箱...简单链接到 Eric Lipperts 博客,如Value types 可能就足够了...
  • 那么你会说在我的示例代码中,如果 dweeb 和 newb 在初始化的右侧都有引用类型 = 他们可能引用相同的东西?
  • 我不这么认为,他们指的是 LINQ 内存查询定义。您之所以如此平等,是因为您使用了错误的 Assert 方法(如其他答案所述)。
猜你喜欢
  • 1970-01-01
  • 2017-08-17
  • 2022-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-06
相关资源
最近更新 更多