2

Is there a way to store a pointer to immutable types like strings in C#? How can execute: Instance1.SomeFunction(out MyString);

,and store a pointer to MyString inside of Instance1?

AareP
  • 2,355
  • 3
  • 21
  • 28
  • C# seems to have been *designed* to hide pointers from the programmer. Generally speaking, pointer manipulation unnecessarily complicates C# code, as there's usually a far simpler way to do what you want. – Whatsit Feb 19 '09 at 23:12
  • If string variables are references, why the following will have no effect on "s": void main() { string s = "original string"; test1(ref s); test2(); } static string r; static void test1(ref string s) { r = s; } static void test2() { r = "changed string"; } – AareP Feb 20 '09 at 16:27
  • No, but you are right. There's no need for pointers in C#. My question was more of theoretical kind. I was just trying to write C code in C#, and though it was possible, since new language implements at least some kind of native pointers. – AareP Feb 20 '09 at 16:30

4 Answers4

0

I have been fighting with pointers in C# for a while now, and was amazed by the lack of options. You encounter all kinds of obscure obstacles when dealing with pointers and pointer arguments in C#:

  • you cannot create native pointers to managed types, not even to strings
  • you cannot save immutable out/ref-arguments for later usage
  • you cannot have optional/nullable out/ref-arguments, even though "null" is the default state of string type
  • you cannot use passed out/ref-arguments inside lambda expressions

Pretty neat solution I found recently, and also the reason for this post is:

void Test()
{
  string ret = "";
  SomeFunction(a=>ret=a);
}

void SomeFunction(string_ptr str)
{
   str("setting string value");
}

delegate void string_ptr(string a);
AareP
  • 2,355
  • 3
  • 21
  • 28
  • And the delegate is not a pointer - it's a setter (you can't get the value with it). – configurator Feb 19 '09 at 22:33
  • Here's delegate with setter ability :) static void Main() { string s = "s"; test(a=>s=a??s); } static void test(string_ptr s) { string r1 = s(null); s("change string"); string r2 = s(null); } delegate string string_ptr(string a); – AareP Feb 20 '09 at 15:17
  • * setter ability -> getter ability – AareP Feb 20 '09 at 15:17
0

Use this class as a pointer (note: untested notepad code, might need some fixing):

public class Box<T> {
    public Box(T value) { this.Value = value; }

    public T Value { get; set; }

    public static implicit operator T(Box<T> box) {
        return box.Value;
    }
}

For example,

public void Test() {
    Box<int> number = new Box<int>(10);
    Box<string> text = new Box<string>("PRINT \"Hello, world!\"");

    Console.Write(number);
    Console.Write("    ");
    Console.WriteLine(text);

    F1(number, text);

    Console.Write(number);
    Console.Write("    ");
    Console.WriteLine(text);
    Console.ReadKey();
}

void F1(Box<int> number, Box<string> text) {
    number.Value = 10;
    text.Value = "GOTO 10";
}

Should output

10    PRINT "Hello, world!"
20    GOTO 10
configurator
  • 40,828
  • 14
  • 81
  • 115
  • For me renaming all string and int variables to box and box sounds like a lot of work. May be I'm too lazy.. :) – AareP Feb 20 '09 at 09:52
  • Think about it like this Box is C#'s syntax for int*. It's the only replacement you'll find to pointers, I believe. – configurator Feb 23 '09 at 00:01
  • Wait, this is completely incorrect. When you construct a Box, you are no longer referring to the original string. You are making a copy of it! Modifications on Box's `Value` will *not* update the original string you were referring to. And no, passing it as `ref string` doesn't make one bit of difference. You need to find some different model for doing this. – Dmitri Nesteruk Apr 24 '19 at 20:49
  • I never said it would update the original string. The Box allows you to store a string inside it, so that you could mutate the Value - like storing string pointers. You get a reference-type value this way, that can be passed around, copied into classes, etc., and remains mutable as the same reference. The idea is not to make a `string` variable and a `Box` which would refer to it - it is to make only a `Box`. – configurator May 15 '19 at 15:13
0

In regards to the answer by the asker, what's wrong with:

class Program
{
    static void Main()
    {
        string str = "asdf";
        MakeNull(ref str);
        System.Diagnostics.Debug.Assert(str == null);
    }

    static void MakeNull(ref string s)
    {
        s = null;
    }

}
Dave
  • 4,420
  • 1
  • 34
  • 39
  • Here you cannot store pointer to "s" for later use, for example if you would want to change it later, outside of MakeNull execution. You could do it with normal managed types, because objects are passed by reference by default, but not with immutable string type. – AareP Feb 20 '09 at 09:59
  • What I mean is that the following will have no effect on "s": void main() { string s = "original string"; test1(ref s); test2(); } static string r; static void test1(ref string s) { r = s; } static void test2() { r = "changed string"; } – AareP Feb 20 '09 at 15:13
0

Ok, I found another partial solution to my problem. You can use overloading, if you want some ref/out-arguments to have null values:

void Test()
{
    string ret1 = "", ret2 = "";
    SomeFunction(ref ret1, ref ret2);
    SomeFunction(null, ref ret2);
    SomeFunction(ref ret1, null);
    SomeFunction(null,null);
}

string null_string = "null";

void SomeFunction(ref string ret1,ref string ret2)
{
   if( ret1!=null_string )
       ret1 = "ret 1";
   if( ret2!=null_string )
       ret2 = "ret 2";
}

// Additional overloads, to support null ref arguments
void SomeFunction(string ret1,ref string ret2)
{
    Debug.Assert(ret1==null);
    SomeFunction(null_string,ret2);
}
void SomeFunction(ref string ret1,string ret2)
{
    Debug.Assert(ret2==null);
    SomeFunction(ret1,null_string);
}
void SomeFunction(string ret1,string ret2)
{
    Debug.Assert(ret1==null&&ret2==null);
    SomeFunction(null_string,null_string);
}
AareP
  • 2,355
  • 3
  • 21
  • 28
  • Ok, there is small bug with this solution, that I couldn't yet remove. Apparently c# doesn't support "===" operator, so I can't distinguish normal strings from "null_string"... – AareP Jun 03 '09 at 06:15