C# C语言中的指针替换#
我需要为C#中类似C/C++的指针提供一个替代方法,以便存储在构造函数中传递的变量的引用。我希望本地指针在每次引用值更改时都更改其值。就像一个指针。但我不想在C#中使用真正的指针,因为它们不安全。有解决办法吗C# C语言中的指针替换#,c#,.net,pointers,C#,.net,Pointers,我需要为C#中类似C/C++的指针提供一个替代方法,以便存储在构造函数中传递的变量的引用。我希望本地指针在每次引用值更改时都更改其值。就像一个指针。但我不想在C#中使用真正的指针,因为它们不安全。有解决办法吗 class A { public Int32 X = 10; } class B { public B(Int32 x) { Y = x; }
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中肯定存在指针
int*ptr=&a
看看文档:忘记指针,开始用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
}
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
}
class B
{
private A _a;
public B(A a)
{
_a = a;
}
public A GetA() {
return _a;
}
public void SetA(A value) {
_a = value;
}
}
位图示例:(为简单起见,假设“SomeBitmap”和“AnotherBitmap”是实际位图)
值tpe(如
int
)与参考类型(如MyClass
)之间存在巨大差异。由于您实际上对位图
感兴趣,而是一种引用类型,因此不需要执行任何指针逻辑。变量已经是引用。更改其状态(例如通过修改其任何公共属性)将反映在所有其他引用中
因此,当您的类A
具有类型为Bitmap
的变量时,您也可以从任何其他代码中使用该变量(假设您可以访问该成员,例如,当该成员是private
时,您肯定不能)
更好的方法是将值类型包装为引用类型。考虑这一点:
object o1 = new object();
object o2 = o1;
现在您可以这样使用它:
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
}
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
}
class B
{
private A _a;
public B(A a)
{
_a = a;
}
public A GetA() {
return _a;
}
public void SetA(A value) {
_a = value;
}
}
NET中基本上有3种类型的引用
a
类型的本地/参数/字段,其中a
是引用类型-a类
,接口
,委托
等)Foo*
类型的本地/参数/字段)ref Foo
类型的本地/参数)A
对象实例而不是int
。请参阅@Fildor的答案,了解这方面的演练。C#区分了值类型和引用类型。值类型(除了string
1之外的结构和基元类型)通过值传递(复制),而引用类型(类)本质上是花哨的指针。(顺便说一句,在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);
A a = new A();
B b = new B(a);
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.X);
A a = new A();
B b = new B(a);
a
指的是b
内外的同一对象。更改a.X
将影响调用b.Y
的结果
您还可以直接公开a
:
class B
{
public B(A a)
{
A = a;
}
public A A { get; set; }
}
那么主要是:
关于属性的注记
您应该知道字段和属性之间的区别。字段是数据成员,就像C++一样。属性只是编译器在幕后生成的get/set方法对的一些语法糖。大致相当于这样的东西:
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
}
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
}
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被声明为struct(值类型)。然后getter将返回一个副本。这有时会导致一个对C#初学者来说并不明显的问题
struct A // value type
{
public Int32 X; // with a value type field
public A(Int32 x) { X = x; }
}
如果A是一个struct,那么
b.A.X=11代码>
您将得到一个编译器错误:“无法修改'b.a.X'的返回值,因为它不是变量”
原因是b.A
返回了一份副本,因此如果您在其中更改了X
,则该行之后的更改将丢失。您必须替换整个实例:
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
另外,在C#中,您通常会编写int
,而不是Int32
1string
是引用类型,但是它是不可变的(所有“修改”字符串的操作都返回单独的string
实例)。您可以通过将引用传递给a
而不是int
,来解决此问题,然后您可以执行public int Y=>a.X
。X
值按值传递到ctor。您可以在B的ctor中使用ref
关键字,使ctor参数通过引用而不是通过值传递。在任何情况下,如果你要传递一个Bitmap
类型的参数,我看不出让程序保持现状有什么问题,因为Bitmap
是一个引用类型,所以你已经有了引用(和指针).所有不是从ValueType
继承的内容都是pointer@HimBromBeere完全同意你的第一个修正-迂腐的观点,尽管:“无论如何它是通过引用传递的”-不,值是引用,通过值我需要…但我不想一旦你学会了C#basics,这些被误导的情绪和想法就会消失。你需要为此使用不安全。是的,但在C#中,你需要将其声明为“不安全”,我想绕过它是的,这是存在的,但在使用不安全代码时,你需要非常非常小心。在本例中,OP希望将其存储为字段。如果您正在谈论的是一个“内部指针”(即您需要使用fixed
来获得的东西),那么这将导致灾难,因为在fixed
块结束时,该值应被视为死值,因为此时GC可以移动原始对象(以及您的非托管po)