C# 如何仅使用它们的引用将对象交换为 inherite class 的对象 - 这可能吗?

C# how swap object to object of inherite class with only their reference - It is posible?

编辑:考虑到我无法访问列表

编辑:我将示例更改为更高级

编辑:固定示例;P

编辑:再次编辑 我确信我被否决了,因为你们不明白我的考虑的来源。我知道在 C++ 中使用指针是可行的,但不确定它在 C# 中是否仍然可行。而且我没有问,因为我不知道如何更改列表中的元素!我只想在不访问该列表的情况下完成它!这只是示例,因为实际的示例太复杂了,无法在此处介绍...

我想知道是否可以做这样的事情 class 傅 { public int foo = 100; 事件处理程序;

        public Foo()
        {
            something += smth;
        }

        public void doSmth()
        {
            something(this, EventArgs.Empty);
        }

        public static void smth(object sender, EventArgs e)
        {
            sender = new Foo();
        }
    }

    class Boo : Foo
    {
        EventHandler<EventArgs> something;

        public Boo()
        {
            foo = 1;
            something += smth;
        }           

    }
    static void Main(string[] args)
    {
        List<Foo> list = new List<Foo>();

        Foo foo = new Boo();
        list.Add(foo);

        foreach (Foo f in list)
            f.doSmth();

        foreach (Foo f in list)
            Console.WriteLine(f.foo);

        Console.ReadKey();
    }

我的输出是 1,但我想得到 100。可以通过引用从列表中更改对象吗?

是的,但您没有得到您认为的参考资料:

Foo boo = list[0];
boo = new Boo;      

这会创建一个 new 引用(称为 boo)并将 list[0] 中的引用分配给它。然后,您将一个 Boo 对象分配给那个 新的本地 引用。当您遍历 List 时,存储在 那里 的引用根本没有改变,所以您会看到行为。

相反,只写:

list[0] = new Boo();

注意我实际上不确定这是否有效,所以我测试了它,它确实有效!因为代码有点奇怪,我建议找到一种不同的方法来改变它(比如删除旧对象并添加新对象)以改进 readability/maintainability.

        List<FancyText> test = new List<FancyText>();
        test.Add(new FancyText { Text = "test" });
        test[0] = new FancyText() { Text = "final" };

集合包含其中包含 "final" 的对象。

更新对于您的编辑,您可以几乎这样做:

private delegate void refHandler (ref Award sender);
private event refHandler test;

但是,您不能将 this 作为 ref 参数传递,因为它是只读的(有道理,对吧?您不能将自己分配给其他对象,那会很奇怪)。

不,这是不可能的。当您分配一个新引用时,boo 不再引用旧位置,但 list[0] 仍然在那里保留一个引用并且更改 boo 的引用不会影响它。因为它们之间没有联系,所以您可以将它们视为两个不同的变量,它们持有对同一位置的引用。像这样:

string foo = "foo";
string bar = foo;
bar = "bar";

更改 bar 的引用不会影响 foo。那就是行为或引用类型。仅当您在函数 parameters.Have 中使用 ref 修饰符时,才能更改变量引用查看此问题以获取有关该问题的更多信息:What is the use of “ref” for reference-type variables in C#?

这与继承无关。您根本就没有修改过列表。看这段代码:

Foo boo = list[0];
boo = new Boo();

在第一行之后,boolist 中的第一个元素引用相同的内存对象。但是在 second 行之后,它引用了一个 new 内存对象。 不是 列表中的第一个元素。在调试器中停在那里并检查对象和列表,它们是不同的。

然后您继续打印列表中的元素。您永远不会打印 boo 的值,也永远不会修改列表。要更新列表中的元素,需要设置:

list[0] = boo;

编辑: 您更新的示例甚至无法编译。此代码无效:

foreach (Foo f in list)
    f.doSmth();

因为 Foo 上没有名为 doSmth() 的方法。您是否要检查集合中的任何给定元素是否是 Boo 的实例并在是时调用该方法?在这种情况下,您可以检查类型:

foreach (Foo f in list)
    if (f is Boo)
        (f as Boo).doSmth();

尽管在 大多数 情况下,我认为这并不是真正好的设计。当然,有些情况需要这样做。但更有可能的是,您的 FooBoo 建模在某处破坏了抽象。如果集合是 Foo 类型,那么对该集合的任何操作 应该 只能是用户对 Foo.

类型的操作

下面将创建一个变量 boo,并引用 list 中第一个位置的 Foo 对象,即您所做的第一个 new Foo()

Foo boo = list[0];

当您执行以下操作时,您会用对新构造的 Boo 对象的引用覆盖变量 booFoo 对象的引用。

boo = new Boo;

要执行手动测试的具体要求,您可以执行以下操作

Foo boo = list[0] == new Boo();

这将更新变量 boolist 中的第一个位置,并使用对新创建的 Boo 对象的新引用。这将输出:

1
100

现在,说到这里。技术上可以直接使用 unsafefixed 关键字来引用。这将增加几个限制。这是我使用不安全代码复制您的代码的最佳尝试:

//Requres project properties be set to Allow Unsafe Code
struct Foo
{
    public int Bar { get; set; }
}

static unsafe void Main(string[] args)
{
    Foo[] list = new Foo[2];
    list[0] = new Foo { Bar = 100 };
    Foo foo = new Foo { Bar = 100 };
    list[1] = foo;

    fixed (Foo* boo = list)
        *boo = new Foo { Bar = 1 };

    foreach (Foo f in list)
        Console.WriteLine(f.Bar); //Prints 1 then 100

    Console.ReadKey();
}

这也会输出:

1
100

然而,这并不是一个普遍的例子。如果您想指向列表中 0 以外的索引,会发生什么情况。您必须将 fixed 部分替换为以下内容:

fixed (Foo* plist = list)
{
    const int offset = 1;
    Foo* boo = plist + offset;
    *boo = new Foo { Bar = 1 };
}

这将输出:

100
1

你失去的是引用 class 对象,只有结构,这意味着没有继承,并且必须使用 fixed 关键字,可能还有更多。