C#列表索引运算符不';t将引用的副本返回到引用类型

C#列表索引运算符不';t将引用的副本返回到引用类型,c#,indexing,reference,return,C#,Indexing,Reference,Return,这是我无法理解的事情。我有以下C#中的示例代码: 类测试程序 { 静态void Main() { 风险值情景=新情景(10); var persons=scenario.GetPersons();//返回指向内部列表的引用副本 persons[0]=new Person(“Modified”);//为什么索引运算符返回实际对象,而不是对象引用的副本,如下所示? Console.WriteLine(scenario.Persons[0].Name);//修改了内部列表 Console.WriteL

这是我无法理解的事情。我有以下C#中的示例代码:

类测试程序
{
静态void Main()
{
风险值情景=新情景(10);
var persons=scenario.GetPersons();//返回指向内部列表的引用副本
persons[0]=new Person(“Modified”);//为什么索引运算符返回实际对象,而不是对象引用的副本,如下所示?
Console.WriteLine(scenario.Persons[0].Name);//修改了内部列表
Console.WriteLine(“指向同一对象:+(persons[0]==scenario.persons[0]);//两个引用都指向同一对象
var pppp=scenario.GetP();//返回指向内部对象的引用的副本
pppp=new Person(“Modified”);//覆盖引用的副本不会像预期的那样影响原始对象
Console.WriteLine(scenario.p.Name);
WriteLine(“指向同一对象:”+(pppp==scenario.p));
var pppp2=方案[0];//返回指向内部对象的引用的副本
pppp2=newperson(“Modified”);//正如预期的那样,覆盖引用的副本对原始对象没有影响
Console.WriteLine(scenario.p.Name);
WriteLine(“指向同一对象:”+(pppp2==scenario.p));
Console.ReadKey();
}
}
公共阶层人士
{
公共字符串名称{get;set;}
公众人物(字符串名称)
{
名称=名称;
}
}
公共类场景
{
公众人士p=新人士(“DDD”);
公众人物
{
返回p;
}
公众人士本[int索引]
{
获取{return p;}
}
公职人员;
公共场景(人)
{
人员=新名单(NR人员);
对于(int i=0;i
所以,我的问题是,为什么List的index操作符似乎返回内部对象?我的印象是,方法/重载运算符在传递/返回引用类型时,默认情况下会复制并按值返回它。这意味着应该返回指向同一对象的新引用。与后续pppp和pppp2引用的情况一样,其行为符合预期

我已经用dotpeek查看了列表实现,但没有看到任何启示。据我所知,只能从C#7.0开始支持将引用返回到引用类型

那么这是怎么发生的呢?我错过什么了吗?编译器是否在做一些诡计来实现这一点?因为,我不是在抱怨这种行为。在这种情况下,这似乎是你希望发生的事情。但我只是对这种不一致的行为感到惊讶


谢谢。我希望这不是我遗漏的一件非常琐碎的事情。

您描述的行为-传递引用与引用副本-在方法之间传递参数时适用。如果包含
ref
关键字,则传递引用。否则,默认情况下,它是引用的副本

列表的目的是包含一组对对象的引用,并能够维护该集合。因此,如果您这样做,可以预期:

persons[0] = new Person("Modified"); 
var pppp2 = scenario[0];
您正在用一个新的引用替换列表中第一个位置的引用

执行此操作时:

persons[0] = new Person("Modified"); 
var pppp2 = scenario[0];
您正在创建一个变量,该变量包含对
方案
实例的引用。然后可以使用不同的引用(或
null
)更新该变量


实际上,在这两种情况下,你都在做同样的事情。将
persons
视为引用的集合,而
persons[0]
是该集合中的单个引用。无论是更新变量(
pppp2
)还是列表元素(
persons[0]
),您都在更新它包含的引用

在你看来,试着用
persons.Index0
替换
persons[0]
,看看你是否能看到
persons.Index0=新的人(“修改的”)
pppp=新人(“修改”)我想它会变得清晰。是的,你正在用指向新对象的指针覆盖指针,而不是对象本身。我想它现在被清除了。我不知道为什么我觉得persons[0]会返回(调用索引器的get)以返回我希望覆盖的副本。但实际上,它是在调用索引器的setter。并传入对新对象的引用。谢谢大家!我认为我希望它能像C++那样工作(如果我没有错的话,那就是它在那里工作的方式,对吧?)C++完全相同(如果你总是把C<代码>人<代码> > C++的<代码>人*>代码>”AlexeiLevenkov:我在C++中不是很有经验的,所以也许我缺少了一些东西,但是下面的代码对我的行为不同。下标运算符返回对内部对象的引用,而在C#中,没有任何内容返回给调用方,而是作为参数接收。现在我明白了,我对其他事情感到困惑。我的印象是C++指针不能指向其他对象,不像指针可以。那么,为什么我可以在下面的C++示例中指向返回的引用对象?