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();
在第一行之后,boo
与 list
中的第一个元素引用相同的内存对象。但是在 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();
尽管在 大多数 情况下,我认为这并不是真正好的设计。当然,有些情况需要这样做。但更有可能的是,您的 Foo
和 Boo
建模在某处破坏了抽象。如果集合是 Foo
类型,那么对该集合的任何操作 应该 只能是用户对 Foo
.
类型的操作
下面将创建一个变量 boo
,并引用 list
中第一个位置的 Foo
对象,即您所做的第一个 new Foo()
。
Foo boo = list[0];
当您执行以下操作时,您会用对新构造的 Boo
对象的引用覆盖变量 boo
对 Foo
对象的引用。
boo = new Boo;
要执行手动测试的具体要求,您可以执行以下操作
Foo boo = list[0] == new Boo();
这将更新变量 boo
和 list
中的第一个位置,并使用对新创建的 Boo 对象的新引用。这将输出:
1
100
现在,说到这里。技术上可以直接使用 unsafe
和 fixed
关键字来引用。这将增加几个限制。这是我使用不安全代码复制您的代码的最佳尝试:
//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 关键字,可能还有更多。
编辑:考虑到我无法访问列表
编辑:我将示例更改为更高级
编辑:固定示例;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();
在第一行之后,boo
与 list
中的第一个元素引用相同的内存对象。但是在 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();
尽管在 大多数 情况下,我认为这并不是真正好的设计。当然,有些情况需要这样做。但更有可能的是,您的 Foo
和 Boo
建模在某处破坏了抽象。如果集合是 Foo
类型,那么对该集合的任何操作 应该 只能是用户对 Foo
.
下面将创建一个变量 boo
,并引用 list
中第一个位置的 Foo
对象,即您所做的第一个 new Foo()
。
Foo boo = list[0];
当您执行以下操作时,您会用对新构造的 Boo
对象的引用覆盖变量 boo
对 Foo
对象的引用。
boo = new Boo;
要执行手动测试的具体要求,您可以执行以下操作
Foo boo = list[0] == new Boo();
这将更新变量 boo
和 list
中的第一个位置,并使用对新创建的 Boo 对象的新引用。这将输出:
1
100
现在,说到这里。技术上可以直接使用 unsafe
和 fixed
关键字来引用。这将增加几个限制。这是我使用不安全代码复制您的代码的最佳尝试:
//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 关键字,可能还有更多。