C#:指向多个整数的引用/指针数组
我想在一个数组中保留对一些短裤的引用。我认为我可以创建短裤,然后将它们添加到阵列中。所以每次更改被引用对象时,这都会反映在数组中,反之亦然。做一些试验使我确信,它不是那样工作的。事实上,它看起来像是传递了值,但不是引用 下面的代码创建了两个短片,将它们作为对象添加到数组中,然后更改原始短片。然而,当访问数组中的假定引用短对象时,它没有改变,这使我相信它是一个与原始对象无关的全新对象C#:指向多个整数的引用/指针数组,c#,pointers,integer,reference,short,C#,Pointers,Integer,Reference,Short,我想在一个数组中保留对一些短裤的引用。我认为我可以创建短裤,然后将它们添加到阵列中。所以每次更改被引用对象时,这都会反映在数组中,反之亦然。做一些试验使我确信,它不是那样工作的。事实上,它看起来像是传递了值,但不是引用 下面的代码创建了两个短片,将它们作为对象添加到数组中,然后更改原始短片。然而,当访问数组中的假定引用短对象时,它没有改变,这使我相信它是一个与原始对象无关的全新对象 Console.WriteLine("Testing simple references:");
Console.WriteLine("Testing simple references:");
short v1 = 1;
short v2 = 2;
object[] vs = new object[2];
vs[0] = v1;
vs[1] = v2;
v1 = 1024;
v2 = 512;
Console.WriteLine(" v1: " + (short)vs[0]);
Console.WriteLine(" v2: " + (short)vs[1]);
我在这里误解了一些基本的东西,如果有人能解释一下,也许能给我指出一个解决方案,我会很感激的 基本问题是
short
是一个结构而不是对象。所以基本上一个short
数组实际上是一个short
数组,而不是一个对短对象的引用数组
要解决这个问题,你可以在一节课中“框”出短文(但这会很乏味)
尝试以下方法:
public class MyShort { public Value { get; set; } }
Short
是一个,但您试图让它表现得像一个
您可以使用short
属性创建一个类,然后使用该类的数组:
public class MyShort
{
public short Value {get; set;}
}
public class SomeOtherClass
{
public void SomeMethod()
{
MyShort[] array = new MyShort[2];
array[0] = new MyShort {Value = 5};
array[1] = new MyShort {Value = 2};
array[0].Value = 3;
}
}
您可能需要做一些工作来使它更平滑(比如实现从
short
到包装类的转换,然后再返回)。C类型系统中有两种类型“值类型”和“引用类型”
值类型按值复制;复制一个对象时,会得到一个与原始对象无关的全新对象
引用类型按引用复制;复制一个引用时,实际上是将引用复制到某个存储位置。得到两个引用,它们都引用一个对象
短裤是价值型的
如果希望short成为引用类型,则可以制作引用类型包装器:
class ReferenceType<T> where T : struct
{
public T Value { get; set }
public ReferenceType(T value) { this.Value = value; }
}
var v1 = new ReferenceType<short>(1);
var v2 = new ReferenceType<short>(2);
var vs = new ReferenceType<short>[2] { v1, v2 };
v1.Value = 1024;
v2.Value = 512;
Console.WriteLine(vs[0].Value);
Console.WriteLine(vs[1].Value);
现在“x”和“y”是同一变量的两个名称。然而,只有当别名变量是方法的形式参数时,“为另一个变量生成别名”的概念才适用于C#。一般来说,没有办法做到这一点
现在,理论上我们可以做一些你想做的事情。我们可以支持“ref locals”:
更新:我在这里讨论的“理论”特性被添加到C#7.0中
也就是说,rv1成为v1的别名。C#不支持这一点,但CLR支持,因此我们可以支持它。但是,CLR不支持生成“ref”元素类型的数组或存储ref的字段。所以从这个意义上说,你不能做你想做的事
C#确实支持一些特殊的“隐藏”特性,用于传递对象,这些对象的行为类似于对变量的引用,但比上面提到的“两个委托”引用更轻。然而,这些特殊功能只适用于奇怪的互操作场景,我建议不要使用它们。(再说一次,你不能创建一个存储类型化引用的数组。)我不认为我会在这个答案中更多地讨论这些特性;相信我,你真的不想去那里。short类型是一种类型,它不像参考类型那样工作,而参考类型的行为就像你期望你的短裤那样。将值类型指定给变量时,将指定其值,而不是其引用
vs[0]
将保存您分配给v1
的值的副本
如果在更改原始值时确实需要更改数组中的值,则需要在引用类型中换行。以下是一个例子:
public class ShortHolder {
public short Value { get; set; }
}
然后你可以这样使用它:
var v1 = new ShortHolder() { Value=123; }
var shortArray = new ShortHolder[1];
shortArray[0] = v1;
public class ShortWrapper
{
public short ShortValue {get; set;}
}
class Program
{
static void Main(string[] args)
{
ShortWrapper short1 = new ShortWrapper{ ShortValue = 1};
ShortWrapper short2 = new ShortWrapper { ShortValue = 2 };
ShortWrapper[] shorts = new ShortWrapper[] { short1, short2 };
shorts[0].ShortValue = 5;
Console.WriteLine(short1.ShortValue);
}
}
如果更改
v1.Value
,则shortArray[0]。Value
也将更改。值类型称为值类型,因为它们在传递给方法或通过=运算符赋值时按值传递
另一种(也是更正确的)看法是,short、int等是不可变的=>它们不能更改。所以你基本上不能改变一个短线。如果需要在某处更改short类型的对象,则需要创建一个类来保存该对象,如下所示:
var v1 = new ShortHolder() { Value=123; }
var shortArray = new ShortHolder[1];
shortArray[0] = v1;
public class ShortWrapper
{
public short ShortValue {get; set;}
}
class Program
{
static void Main(string[] args)
{
ShortWrapper short1 = new ShortWrapper{ ShortValue = 1};
ShortWrapper short2 = new ShortWrapper { ShortValue = 2 };
ShortWrapper[] shorts = new ShortWrapper[] { short1, short2 };
shorts[0].ShortValue = 5;
Console.WriteLine(short1.ShortValue);
}
}
本质上,代码是用一个新对象替换short类型的对象
顺便说一句,如果你需要包一个裸体短裤,你的设计可能有问题。您应该已经在使用一些更复杂的对象,或者应该以其他方式处理短裤数组。但我猜您只是在测试。如果向类添加转换运算符,您可以透明地使用
ReferenceType
,就好像float、int等实际上是引用类型一样:
class ReferenceType<T> where T : struct
{
public T Value { get; set; }
public ReferenceType(T value) { this.Value = value; }
public static implicit operator ReferenceType<T>(T b)
{
ReferenceType<T> r = new ReferenceType<T>(b);
return r;
}
public static implicit operator T(ReferenceType<T> b)
{
return b.Value;
}
}
ReferenceType<float> f1 = new ReferenceType(100f);
f1 = 200f;
float f2 = f1;
类引用类型,其中T:struct
{
公共T值{get;set;}
公共引用类型(T值){this.value=value;}
公共静态隐式运算符引用类型(TB)
{
ReferenceType r=新的ReferenceType(b);
返回r;
}
公共静态隐式运算符T(引用类型b)
{
返回b.值;
}
}
ReferenceType f1=新的ReferenceType(100f);
f1=200f;
浮动f2=f1;
通过使用
显式
限定符而不是隐式
,您可以要求对这些转换进行强制转换,如果您想以牺牲一点冗长为代价使事情更清楚。我将在该类中添加一个where T:struct
。它不是严格必要的,但更符合类型的目标。由于Eric没有给出关于C#的“隐藏”特性的详细信息,我发布了一个关于这些特性的链接:我震惊地发现short是一个结构。一些需要确认的链接,对于稍后来到这里的人:,
public class ShortWrapper
{
public short ShortValue {get; set;}
}
class Program
{
static void Main(string[] args)
{
ShortWrapper short1 = new ShortWrapper{ ShortValue = 1};
ShortWrapper short2 = new ShortWrapper { ShortValue = 2 };
ShortWrapper[] shorts = new ShortWrapper[] { short1, short2 };
shorts[0].ShortValue = 5;
Console.WriteLine(short1.ShortValue);
}
}
class ReferenceType<T> where T : struct
{
public T Value { get; set; }
public ReferenceType(T value) { this.Value = value; }
public static implicit operator ReferenceType<T>(T b)
{
ReferenceType<T> r = new ReferenceType<T>(b);
return r;
}
public static implicit operator T(ReferenceType<T> b)
{
return b.Value;
}
}
ReferenceType<float> f1 = new ReferenceType(100f);
f1 = 200f;
float f2 = f1;