【问题标题】:anything like pointers in c#?像c#中的指针一样吗?
【发布时间】:2020-12-04 08:47:06
【问题描述】:

我是 c# 新手(一般是编码),我找不到任何等效的指针。
当我搜索谷歌时,我得到了安全/不安全之类的东西,但这不是我需要的。

就像在 c++ 中一样,如果你有一个指针并且它指向某个值,那么指针的变化会导致原始变量的变化。 c#中有这样的东西吗?
例子-

static class universal
{
   public static int a = 10;
}

class class_a
{
   public void change1()
   {
      universal.a--;
   }
}

class class_b
{
   public void change2()
   {
      some_keyword temp = universal.a; //change in temp gives change in a
      temp-= 5; //the purpose of temp is to NOT have to write universal.a each time
   }
}

...

static void Main(string[] args)
{
   class_b B = new class_b();
   class_a A = new class_a();
   A.change1();
   Console.WriteLine(universal.a);//it will print 9

   B.change2();
   Console.WriteLine(universal.a);//it will print 4
   Console.ReadKey();
}

编辑- 谢谢@Sweeper 我得到了答案 我不得不使用 ref int temp = ref universal.a;

【问题讨论】:

  • 就像在 c++ 中一样,如果你有一个指针并且它指向某个值,那么指针的变化会导致原始变量的变化。 c# 中有这样的东西吗? - 再看一遍!
  • Pass By Reference 会解决你的问题。

标签: c# c++ class pointers call-by-value


【解决方案1】:

如果您不想要不安全的代码,我可以考虑两种选择。

包装对象

你可以创建一个这样的类,它包装了一个int

public class IntWrapper {
    public int Value { get; set; }
}

然后将a的类型改为这个类:

static class Universal
{
   public static IntWrapper a = new IntWrapper { Value = 10 };
}

class class_a
{
   public void change1()
   {
      universal.a.Value--;
   }
}

class class_b
{
   public void change2()
   {
      Universal temp = universal.a; //change in temp gives change in a
      temp.Value -= 5;
   }
}

之所以可行,是因为类是引用类型,a 持有一个指向IntWrapper 对象的引用(类似于指针)。 = 复制对temp 的引用,而不创建新对象。 tempa 都指向同一个对象。

ref locals

这是一种更简单的方法,但仅适用于局部变量。例如,您不能将其用于字段。

public void change2()
{
    ref int temp = ref universal.a; //change in temp gives change in a
    temp -= 5;
}

【讨论】:

  • 其实我不想在函数 change2() 中每次都写“universal.a”,而是用一个变量名 temp 替换它,实际上必须写 temp.a违背目的¯_(ツ)_/¯
  • @WiredDifferently 糟糕。我复制粘贴了您的代码,不小心将.a 留在了那里。如果您使用 ref 本地人,则不需要 .a。如果你使用包装对象,你确实需要.Value,但不需要.a
  • 它仍然给出错误提示-“无法用值初始化一个引用变量”
  • @WiredDifferently 不要忘记refuniversal.a 之前的单词。我忘记了,现在我把它添加进去了。
  • 非常感谢我得到了解决方案,但出于纯粹的好奇,这个 ref 可以用于所有数据类型吗?就像我正在处理一些硒代码,我需要使用 IWebDriver 代替 int (如果你不想回答这个问题,它与我发布的 Q 并不完全相关)
【解决方案2】:

C# 有references 与指针非常相似。如果ab 都是对同一个对象的引用,那么a 的变化也会在b 中看到。

例如,在:

class X {
    public int val;
}

void Main()
{
    var a = new X();
    var b = a;
    a.val = 6;
    Console.WriteLine(b.val);
}

6 将被写入。

如果将X 的声明从class 更改为struct,则ab 将不再是引用,而0 将被写入。

【讨论】:

  • 实际上我的全部观点是替换每次都必须编写“universal.a”,而只需编写“temp”(单个变量)并在函数“change2”中使用该“temp” "
【解决方案3】:

在 c# 中使用Pass By Reference 代替指针,这是更正后的代码

static class universal
{
   public static int a = 10;
}

class class_a
{
   public void change1()
   {
      universal.a--;
   }
}

class class_b
{
   public void change2(ref int val)//use ref keyword for reference
   {
       int temp = val; //change in temp gives change in a
       val -= 5;
   }
}

static void Main(string[] args)
{
   class_b B = new class_b();
   class_a A = new class_a();
   A.change1();
   Console.WriteLine(universal.a);//it will print 9

   B.change2(ref universal.a); //pass value by reference using ref keyword
   Console.WriteLine(universal.a);//it will print 4
   Console.ReadKey();
}

【讨论】:

  • 有什么方法可以不用在函数参数中使用 ref 而是直接在函数内部赋值?我的全部目的是不必每次都写universal.a?并通过函数 change2() 简单地将其替换为 temp ,但 temp 的变化仍然会导致 Universal.a 的变化。a
  • 你会在这里找到答案:stackoverflow.com/questions/2333574/…
  • 使用pass by reference,你已经声明了该成员为静态的,为什么不直接使用呢?
【解决方案4】:

在某些情况下(当非常需要优化时)您可以使用几乎类似于 C 的指针。您只能通过将代码放在unsafe 范围内明确指定您意识到风险来做到这一点:

unsafe
{
    int number = 777;
    int* ptr = &number;

    Console.WriteLine($"Data that pointer points to is: {number} ");
    Console.WriteLine($"Address that pointer holds: {(int)ptr}");
}

不安全的上下文允许您直接使用指针。请注意,默认情况下,您的项目会关闭此选项。要对此进行测试,您需要右键单击项目>Properties>Build - Allow unsafe code

【讨论】:

    【解决方案5】:

    像这样?

    using System;
    
    namespace Demo
    {
        class Program
        {
            static void Main()
            {
                var test = new class_a();
                test.change1();
                Console.WriteLine(universal.a); // Prints 18
            }
        }
    
        static class universal
        {
            public static int a = 10;
        }
    
        class class_a
        {
            public void change1()
            {
                ref int x = ref universal.a;
    
                ++x;
                ++x;
                ++x;
                x += 5;
            }
        }
    }
    

    [编辑:我注意到这与 Sweeper 答案的最后一部分相同,但我将把它留在这里,因为它只关注那个解决方案。]

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-24
      相关资源
      最近更新 更多