C#中的指针替换



我需要一个C#中类似C/C++的指针的替代方案,这样我就可以存储构造函数中传递的变量的引用。我希望我的本地指针在每次引用值更改时都更改其值。就像一个指针。但是我不想在C#中使用真正的指针,因为它们是不安全的。有变通办法吗?

class A
{
public Int32 X = 10;
}
class B
{
public B(Int32 x)
{
Y = x;
}
public Int32 Y { get; set; }
}
static void Main(string[] args)
{
A a = new A();
B b = new B(a.X);
Console.WriteLine(b.Y); // 10
a.X = 11;
Console.WriteLine(b.Y); // 10, but I want it to be 11
}

在C#中编码时忘记指针并开始用C#思考:D

我会这样做:

public interface IXProvider
{
int X {get;}
}
class A : IXProvider
{
public int X {get; set;} = 10;
}
class B
{
public B(IXProvider x)
{
_x = x;
}
private readonly IXProvider _x;
public int Y => _x.X;
}
static void Main(string[] args)
{
A a = new A();
B b = new B(a);
Console.WriteLine(b.Y); // 10
a.X = 11;
Console.WriteLine(b.Y); // 11
}

位图示例:(为了简单起见,假设"SomeBitmap"one_answers"AnotherBitmap"为实际位图(

public interface IBitmapProvider
{
Bitmap X {get;}
}
class A : IBitmapProvider
{
public Bitmap X {get; set;} = SomeBitmap;
}
class B
{
public B(IBitmapProvider x)
{
_x = x;
}
private readonly IBitmapProvider _x;
public Bitmap Y => _x.X;
}
static void Main(string[] args)
{
A a = new A();
B b = new B(a);
Console.WriteLine(b.Y); // SomeBitmap
a.X = AnotherBitmap;
Console.WriteLine(b.Y); // AnotherBitmap
}

中基本上有3种类型的引用。净

  1. 对象引用(即A类型的本地/param/字段,其中A是引用类型-classinterfacedelegate等(
  2. 非托管指针(即Foo*类型的本地/param/字段(
  3. 托管指针(即ref Foo类型的本地/param(

你(相当明智地(说你不想使用";2〃;,以及";3〃;可以在堆栈上仅使用(作为局部变量或参数(;1〃;,这是可能的。例如,通过传入A对象实例而不是int。请参阅@Fildor的回答,了解这方面的演练。

更好的方法是将值类型封装为引用类型。考虑一下:

object o1 = new object();
object o2 = o1;

现在你可以这样使用它:

class Obj {
public int Val;
}
void Main() {
Obj o1 = new Obj();
o1.Val = 5;
Obj o2 = o1;
o2.Val = 8;
//o1.Val is 8 now
}

int等值类型与MyClass等参考类型之间存在巨大差异。由于您实际上对BitMap感兴趣,引用类型,因此不需要执行任何指针逻辑。变量已引用。更改其状态(例如通过修改其任何公共属性(无论如何都会反映在所有其他引用中。

因此,当类A具有类型为Bitmap的变量时,您也可以使用任何其他代码中的变量(假设您可以访问该成员,例如,当它是private时,您肯定不能(。

A a = new A();
B b = new B(a.Image); // this will just reference the bitmap instead of copying it
b.Image.Modify(); // this will also be reflected in a.x

我对C#不太熟悉,所以我不能提供一个有效的答案,但C#中肯定存在指针。

int* ptr = &a

查看文档:https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/unsafe-code-pointers/pointer-types

C#区分值类型引用类型。值类型(结构和基元类型,string1除外(是按值传递的(复制(,而引用类型(类(本质上是花哨的指针。(顺便说一句,在IDE中,如果你把鼠标悬停在一个变量上,它会告诉你它是一个类还是一个结构(。

所以,记住这一点,这就是你的代码所做的:

class A       // reference type
{
public Int32 X = 10;     // with a value type field
}
class B       // reference type
{
// The ctor takes in a value type parameter; a copy of the 
// value is passed in (pretty much like in C++)
public B(Int32 x)
{
Y = x;       // this now contains its own copy
}
// value type PROPERTY -- see below
public Int32 Y { get; set; }
}

所以,在你的主要方法中,当你进行时

A a = new A();
B b = new B(a.X);

b。Y与a.X没有连接,因为一旦对a.X求值,构造函数就会获得a.X的副本。

你能做的最简单的事情是让B的构造函数接受a类型的参数,然后在内部存储对a的引用:

class B
{
private A _a;

public B(A a)    // a is passed in by reference
{
_a = a;       
}
public Int32 Y { 
get => _a.X; 
set => _a.X = value; 
}     
}

现在当你做

A a = new A();
B b = new B(a);

CCD_ 18指代CCD_。更改a.X会影响调用b.Y的结果。

您也可以直接暴露a

class B
{
public B(A a)
{
A = a;
}
public A A { get; set; }
}

然后在main((中:

A a = new A();
B b = new B(a);
Console.WriteLine(b.A.X);   // 10
a.X = 11;
Console.WriteLine(b.A.X);   // 11

关于属性的说明

您应该注意字段和属性之间的区别。字段是数据成员,就像C++中一样。属性只是编译器在后台生成的get/set方法对的语法糖。它大致相当于这样的东西:

class B
{
private A _a;

public B(A a)
{
_a = a;       
}
public A GetA() { 
return _a; 
}     
public void SetA(A value) { 
_a = value;
}      
}

在这种情况下,由于A是一个引用类型,它是通过getter的引用返回的。但是现在假设A被声明为一个结构(一个值类型(。然后getter将返回一个副本。这有时会导致一个对C#初学者来说并不明显的问题。

struct A       // value type
{
public Int32 X;     // with a value type field
public A(Int32 x) { X = x; }
}

如果A是一个结构,并且您尝试进行

b.A.X = 11;

你会得到一个编译器错误:;无法修改"b"的返回值。A.X’,因为它不是一个变量";。

原因是b.A返回一个副本,所以如果您更改了它上的X,那么更改将在该行之后丢失。您必须替换整个A实例:

A a = new A(10);   // struct
B b = new B(a);    // class containing a struct

Console.WriteLine(b.A.X);   // 10
a.X = 11;
Console.WriteLine(b.A.X);   // 10  - because A is a value type now
b.A = new A(11);            // setting a property on B works as expected,
// but you can't do b.A.X = 11
Console.WriteLine(b.A.X);   // 11

第页。S.在C#中,通常会编写int而不是Int32


1string是一个引用类型,但它是不可变的(所有"修改"字符串的操作都返回单独的string实例(。

最新更新