[英]List<int> in c#
我无法理解List<int>
背后的逻辑,因为它打破了一些基本规则。
List<int>
应该是值类型而不是引用类型。
ref
关键字传递List<int>
。 所以这意味着它正在显示类似于int的值类型行为。 List<int>
必须由new运算符初始化。 List<int>
也可以为null。 这意味着引用类型行为。 可空类型是不同的,因为它不必由新运算符初始化。
我在这看错了吗?
EDITED-
我应该在原始问题中发布代码。 但它遵循 -
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
ListTest d = new ListTest();
d.Test();
}
}
class ListTest
{
public void ModifyIt(List<int> l)
{
l = returnList();
}
public void Test()
{
List<int> listIsARefType = new List<int>();
ModifyIt(listIsARefType);
Console.WriteLine(listIsARefType.Count); // should have been 1 but is 0
Console.ReadKey(true);
}
public List<int> returnList()
{
List<int> t = new List<int>();
t.Add(1);
return t;
}
}
}
列表应该是值类型而不是引用类型。
错误! int
是值类型。 List<int>
是引用类型。
我认为你的第一颗子弹中有一个错误的假设。 通用List对象绝对是引用类型(在堆上,而不是堆栈)。 不确定为什么你认为你必须通过ref
。 这打印“2”就像它应该:
namespace ConsoleApplication1 {
class Program {
static void Main(string[] args) {
List<int> listIsARefType = new List<int>();
ModifyIt(listIsARefType);
ModifyIt(listIsARefType);
Console.WriteLine(listIsARefType.Count); // 2!
Console.ReadKey(true);
}
static void ModifyIt(List<int> l) {
l.Add(0);
}
}
}
您需要了解传递引用 , 传递值和按值传递引用之间的区别。
在您发布的代码示例中,要传递的参考 List<int>
由值对象。 这意味着您可以改变引用指向的对象,并且调用代码将看到这些更改。 但是,引用本身是按值传递的,因此如果将引用更改为指向另一个对象,则调用代码将不会看到更改。
当您使用ref
关键字时,您将通过引用传递引用。 这意味着您不仅可以更改引用指向的对象,还可以更改引用本身。
考虑这个例子:
class Program
{
static void Main()
{
int foo = 0;
DoSomething1(foo);
Console.WriteLine(foo); // Outputs 0.
DoSomething1(ref foo);
Console.WriteLine(foo); // Outputs 1.
var bar = new List<int>();
DoSomething2(bar);
Console.WriteLine(bar.Count); // Outputs 1.
DoSomething2(ref bar);
Console.WriteLine(bar.Count); // Outputs 0.
}
// Pass by value.
static void DoSomething1(int number)
{
// Can't modify the number!
number++;
}
// Pass by value.
static void DoSomething1(ref int number)
{
// Can modify the number!
number++;
}
// Pass reference by value.
static void DoSomething2(List<int> list)
{
// Can't change the reference, but can mutate the object.
list.Add(25);
}
// Pass reference by reference.
static void DoSomething2(ref List<int> list)
{
// Can change the reference (and mutate the object).
list = new List<int>();
}
}
List<int>
确实是一个引用类型。 但列表中包含的项目是值类型。
然而,可以为Nullable的类型实现为结构( struct Nullable<T> where T : struct
),因此是值类型。 你可以简单写的原因
int? i = 3;
没有new
关键字的是上述语法由编译器自动转换为将执行以下操作的代码:
Nullable<Int32> i = new Nullable<Int32>(3);
为了更好地理解值类型和引用类型语义之间的差异,我建议您阅读Jon Skeet关于此主题的文章,该文章将为您提供大量示例代码示例:
不要把它想象成List<int>
以它写成List<t>
的方式来思考它。
List是一个泛型类 。 它不是结构。 它是一个可以使用值类型和引用类型的泛型类。
List
是一种通用引用类型,您使用值类型为int的类型。 但它仍然是一种参考类型。
在ModifyIt()方法中,当你写'l = returnList()'时; 'l'现在指向内存中的不同位置,而不是Test()方法中listIsARefType的位置。 基本上通过写'l''='某事,你打破了'l'和'listIsARefType'之间的联系。 为了保持链接(确保两个对象,'l'和'listIsARefType'指向内存中的相同位置),您需要只处理'l'对象(例如通过调用对象上的函数),或在ModifyIt()方法的参数中使用ref关键字。
List<int>
是引用类型。 并且它不必作为参考传递。
类型列表中的对象是值类型一种-的,不同的是值类型的对象可能最终装箱(转换成某种引用类型的对象),无论如何,一旦你明白so..scratch这一段。
除了在其他答案中处理的错误假设之外,你说:
List<int>
必须由new运算符初始化...这意味着引用类型行为。
不,在C#中, new
运算符只是调用类型构造函数的语法。 它用于引用和用户定义的值类型( struct
)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.