-1

I am a C++/Java amateur but completely new to C#. My goal is to make a Tree where Nodes are pointers instead of entire objects that are constantly and slowly copied. That way I can simply pass a memory address instead of copying entire objects byte by byte. However, I need to first understand how to use pointers in C#.

  1. Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object. At Program.$(String[] args) on line 19 [*p1 = 45;]. ---Do pointers have to be tied to objects, not allowed to be static (free roaming)? Does the compiler not know the pointer is pointing to an int?
  2. Why can I not use Main() here? Does Main() need to be inside a class/be tied to an object?
  3. How do I know where (inside the code, not the compilation file) to put the unsafe{} block?
  4. What all needs classes and what all can act as stand-alone code? I understand that code reusability screams "Make this a class!" but how do you make code not be tied to an object (i.e. make static but functional code) in C#?
    using System;
    
    //unsafe{} is necessary to use pointers.
    //In addition to this block, add the compiler flag "-unsafe" or set the flag to True
    //FOR VSCode:    Add the following to ProjectName.csproj:
    //                      <PropertyGroup>  <AllowUnsafeBlocks>true</AllowUnsafeBlocks>  </PropertyGroup>
    //static void Main()
    //{
        unsafe
        {
            //The Pointer Data Types will contain a memory address of the variable value.
            //ampersand (&): The Address Operator.     It is used to determine the address of a variable.
            //asterisk  (*): The Indirection Operator. It is used to access the value at an address.
            int* p1=(int*)130, p2;      //Valid   syntax for making 2 pointers
            //int *p3, *p4;             //Invalid syntax for making 2 pointers.
            //Maybe the compiler thinks it's:  int* p3; int** p4; but in 1 statement.
            //Declaring different types in 1 statement is illegal.   int a, (float)b; is illegal
            p2 = (int*)145;     //location p2 is 145 in memory;
            *p1 = 45;   //value at location p1 = 45;
            *p2 = 50;   //value at location p2 = 50;
            Console.WriteLine(  $"adrs{(int)p1}-val{*p1},  adrs{(int)p2}-val{*p2}"  );
            
            int num = 10;     //declare variable
            int* p = &num;    //store variable num's address location in pointer variable p
            Console.WriteLine("Value :{0}", num);
            Console.WriteLine("Address :{0}\n\n\n", (int)p);
        }
    //}

In regards to my questions, please tell me what to elaborate on because I am very clueless about what I don't know, meaning I don't know how to word my questions for easy comprehension.

Also, any DETAILED and understandable sources are greatly appreciated.

Stev
  • 65
  • 1
  • 7
  • 2
    `My goal is to make a Tree where Nodes are pointers instead of entire objects that are constantly and slowly copied. That way I can simply pass a memory address instead of copying entire objects byte by byte.` Objects of a class are reference types. – tkausl Jun 20 '22 at 04:03
  • It appears that what you're trying to do is pointless because, as suggested, classes are reference types so class instances are not copied in the first place. When you pass a method argument by value, which is the default, you are creating a copy of the contents of the specified variable. Reference-type variables contains references, not objects, so you are just creating a copy of a reference. The point of a reference is that the developer can basically treat it as though it were the object but the system treats it pretty much as a pointer. – John Jun 20 '22 at 04:21
  • 2
    As for your question, you have asked multiple questions in one post, which is not allowed. Each question you post must be self-contained, containing all and only the information relevant to that question. If you have multiple questions to ask, even if they are related, then you must post them individually. – John Jun 20 '22 at 04:22

2 Answers2

3

This is a very bad idea, and the reason why you're having so much trouble making it work is that the language wasn't designed this way. In C#, memory is managed, which means amongst other things object can move in memory. That makes pointers inherently difficult to use, and you usually have to pin something to use it.

But really, it's unnecessary. C# has reference types (classes, interfaces, delegates) and value types (structs). A variable of a reference type is really just a reference (essentially a pointer) to an object. Copying a reference is very cheap. So, in that regard, it works exactly like Java.

Now, of course, an int is a value type (it's an alias for the Int32 struct), so an int variable is not a reference, it is the value itself. That said, you can just wrap that into a class if you really need a level of indirection (but ints are also very small so they're cheap to copy).

Also, on the note of being "tied to objects": every method in C# must be part of a class or struct, so you can't have freestanding functions like in C++. But you can make the method static if it doesn't need to be associated to a specific object:

public class Program
{
    public static void Main()
    {
        // ...
    }
}
Etienne de Martel
  • 34,692
  • 8
  • 91
  • 111
0
  1. You have an exception because you don't allocate memory for integers. Actually (int*)130 means that 130 is an address, which means p1 points to nowhere. You need to allocate memory to write and read values:
int v1 = 130, v2 = 45; // allocation
int* p1=&v1, p2; // or U can use stackalloc to allocate int:
                 // int* p1 = stackalloc int[1] { 130 }, p2;  
*p1 = 50; // it's ok because we have already allocated memory for an integer,
          // here we just overwrite the value.
p2 = &v2;  // ok

//p2 = &130; // not ok.
//*p2 = 50;  // not ok. You are trying to dereference null
//p2 = stackalloc int[1] { 45 };  // not ok, You can use a stackalloc expression only in a 
                                  // local variable declaration to initialize the variable.
  1. Starting in C# 9, you don't have to explicitly include a Main method in a console application project. Instead, you can use the top-level statements feature to minimize the code you have to write. In this case, the compiler generates a class and Main method entry point for the application.

  2. If You want to use unsafe features (pointers), you put an unsafe block or unsafe modifier on method/class/struct :) read more . Most of the time you don't want to use unsafe code, it won't give you performance (if you don't know what you're doing) but it will make your code less readable.

  3. You can't. Everything in C# is an object (nearly)(actually you can use static methods (but it's better not to overuse it)).

SAY
  • 26
  • 3