【问题标题】:Do synonyms exist?存在同义词吗?
【发布时间】:2013-06-28 12:00:07
【问题描述】:

有没有办法将一个变量设置为一个对象,并让另一个变量始终等于前一个?

var x = new object();
var y = [synonym of x];
x = null; // then y = null as well

我认为这不存在。

所以我经常使用数组来保存“引用”。

var x = new object[] { new object() };
var y = x;
x[0] = null; // then y[0] = null as well

但感觉有点蹩脚。

【问题讨论】:

  • 你为什么要这样做?
  • 你通常在 C# 中有引用,所以我不确定你的意思。
  • @Skurmedel 我的数组示例不是很清楚吗?
  • refout 参数传递给方法时,您有原始变量的别名。但是你不能在一个方法中做到这一点。
  • @Serge:没问题,我明白你的意思了。您要修改引用,而不是您所引用的对象。

标签: c# keyword


【解决方案1】:

如果您真的需要这样做,您可以执行以下操作,但我认为它仍然很蹩​​脚(:

class RefHolder<T>
{
    public RefHolder(T value)
    {
        Value = value;
    }

    public T Value { get; set; }
}

用法

var o1 = new RefHolder<object>(new object());
var o2 = o1;
o2.Value = null; // now o1.Value is null too

【讨论】:

  • 他说要写:o1 = null 并且 o2 自动变为 null。
  • 我明白了,这就是为什么这仍然是蹩脚的。
  • @Tigran,我很高兴有替代建议。
  • 我猜,一切都会以这样的方式结束……好方法。
  • @Mehmet,它没有数组方法那么混乱。语法甚至看你有什么可以为空的原语。
【解决方案2】:

您可以这样做,但您必须付出的代价是使用未记录的关键字/功能。它们很久以前就在那里,可能不会改变或消失,但是......

它会使您的代码更难阅读(如果语言本身支持它可能会很有用),但它是双向的,您可以在原始对象周围移动,更改也将始终反映到您的“参考”中。它不同于 Mehmet Ataş 的回答,因为您可以将原始对象传递给另一个函数,并且更改也会传播到您的同义词。它们有局限性(它们不能用于类字段),但它们适用于参数和局部变量。

你需要的是一个TypedReference,它持有一个对另一个变量的引用,然后如果你给它分配一个新的值,你就会改变原来的变量。如果有一天他们认为这是一个很好的功能,这在理论上可以为同义词打开大门。

我们来看一个例子:

var text = "initial value";
var synonym = __makeref(text);

现在synonym 是对文本的引用(请注意,它是对text 的引用,而不是它所持有的值)。要从 TypedReference 获取原始值,请使用 __refvalue,如下所示:

Console.WriteLine(__refvalue(synonym, string));

它们具有相同的值:

Debug.Assert(__refvalue(synonym, string) == text);

现在让我们将文本更改为新值:

text = "second value";
Debug.Assert(__refvalue(synonym, string) == text);

反之亦然:

__refvalue(synonym, string) = "third value"; // <---
Debug.Assert(__refvalue(synonym, string) == text);

最后让我们在另一个函数中修改原始变量(不知道引用它会看到一个正常变量):

void ChangeIt(ref string value) { value = "another value"; }

ChangeIt(ref text);
Debug.Assert(__refvalue(synonym, string) == text);

所有这些工作也将重视类型。请注意,这会为变量创建同义词,而不是别名(您可以将它们想象为安全指针 - 在引用类型的情况下指向指针)。让我们试试这个:

void foo1()
{
    string text = "ABC";
    foo2(text);

    // text holds the original value "ABC"
    // not the value modified in foo2
}

void foo2(string value)
{
   value = "123";
   var synonym = __makeref(value);
   __refvalue(value, string) = "456";

   // both value and synonym holds "456";
}

【讨论】:

  • 它根本没有提高可读性,但它回答了这个问题。我很高兴了解这些(即使我不会实际使用它们)。
  • @Serge 是的,我不建议在任何真正的程序中使用它们(不仅因为它们没有记录)。我从来没有觉得我会在 C# 中需要这个功能(同义词)但是......这是我能想象的第一个真正的使用关键字!哈哈
【解决方案3】:

嗯,您基本上是在描述 C++ 引用(或 C 指针)。 这也可以在 C# 中完成,但除非绝对需要,否则您真的不想这样做。

unsafe static void Main(string[] args)
    {
        int a = 5;

        int *b = &a;
        *b = 0;

        Console.WriteLine(a);
    }

这会将0 输出到控制台。

您可以在 MSDN 上的Unsafe Code and Pointers 文章中阅读有关不安全代码的更多信息。

【讨论】:

  • 在 C# 中你不能有指向类的指针,所以这种方法只适用于一些非托管类型。要查看哪些类型可能是指针类型,您可以查看来自 MSDN 的 Pointer types (C# Programming Guide)
【解决方案4】:

这取决于。 .NET 包含引用类型和值类型。值类型是所有基本类型,int、bool 等。加上字符串。引用类型是其他所有内容,包括您为自己创建的任何内容。

例如,值类型...

int a = 3;
int b = a;
b = 5;
// a is still 3

虽然有参考

class Mine {
  public int A { get; set; }
}
Mine A = new Mine() { A = 3; }
Mine B = A;
B.A = 5;
// A.A is now 5.

【讨论】:

  • 我的意思是不,同义词本身不存在,但可以通过使用引用变量而不是值类型来实现。抱歉,如果没有遇到。
  • 这与 Mehmet 较早给出的答案有些相同,但命名不太友好。
  • 同意,Mehmets 的回答是一个实际的解决方案/解决方法,我的只是一个例子。
【解决方案5】:

你可以像这样分配

var parentObject={};

parentobject['child1']="test1";
parentobject['child2']="test2";
parentobject['child3']="test3";

之后

console.log(parentObject);

你得到以下输出

object{child1="test1",child2="test2",child2="test2"}

【讨论】:

  • 这是一个 javascript 答案吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-13
  • 2020-08-14
  • 1970-01-01
  • 1970-01-01
  • 2014-07-05
  • 2014-03-29
  • 2010-11-01
相关资源
最近更新 更多