Pointers are unsafe but I don't understand ref - c#

I want a singleton Problem with a "square" 2x2.
I want to be able to refer to the case by row.
I want to be able to refer to the row by case.
I know I could easily do this in C++ with pointers but it seems like a bad habit to do.
I don't understand how to link my "row" and my "case" together.
The same logic will be there for column but isn't describe in the code
The goal is so changing the value of a Case would affect the value reffered in the Row. How can I achieve this without pointer and with Ref?
class Program
{
static void Main(string[] args)
{
Problem.Instance().Show();
Problem.Instance().Change();
Problem.Instance().Show();
}
public class Problem
{
private Case[] cases = null;
private Row[] rows = null;
// same logic with private Column[] columns = null;
static Problem instance = null;
private Problem()
{
cases = new Case[4];
rows = new Row[2];
int i = 0;
for (i = 0; i < 4; i++)
cases[i] = new Case();
for (i = 0; i < 2; i++)
rows[i] = new Row(i);
}
public static Problem Instance()
{
if (instance == null)
instance = new Problem();
return instance;
}
public Case LinkToRow(int i, ref Row r)
{
cases[i].LinkToRow(r);
return cases[i];
}
public void Show()
{
rows[0].Show();
}
public void Change()
{
cases[0].Change();
cases[1].Change();
}
}
public class Row
{
private Case[] ref cases = null;
public Row(int i)
{
ref Row r = this;
cases = new Case[2];
cases[0] = Problem.Instance().LinkToRow(0, ref r);
cases[1] = Problem.Instance().LinkToRow(1, ref r);
}
public void Show()
{
Console.WriteLine("{0},{1}", cases[0].Val, cases[1].Val);
}
}
public class Case
{
private int val;
private ref Row r = null;
public Case()
{
}
public void LinkToRow(Row rr)
{
r = rr;
}
public int Val { get { return val; } }
public void Change()
{
val++;
}
}
}

In C#, private Row r = null; declares a rebindable reference to an instance of Row. ref is illegal there and not needed.
In C++, private: Row r; would be an instance of Row, not a reference. C++ is a different language with very different rules. C# classes can't "be on the stack"; they're always dynamically allocated, and the only way you can manipulate one is via a reference.
In C#, your private Row r; is already a reference. A C# reference is kind of like a pointer that you don't have to (and can't) explicitly dereference. Because it's always dereferenced, you can't do pointer arithmetic either. They're subject to many of the same polite fictions ("let's make them pretend it's not a pointer") as C++ references. Just take out ref.
A C# struct (e.g. System.DateTime) is more like a stack instance of a C++ class. This is very different from the C++ struct/class distinction.
The C# ref keyword is a different animal. Nothing to do with references.
In C#, the example below illustrates what the ref keyword is for: Passing references by reference instead of by value. That sounds like I'm pulling your leg but I'm not.
To explain it in terms of C++ semantics, passing a C# reference "by value" is like passing a pointer. You can change the object the caller's pointer points at, but you can't change the caller's pointer itself. You have only the value of the caller's pointer.
Passing a C# reference by reference is like passing in a pointer to a pointer: You can set (*p)->Foo = 3;, and you can also set *p = new Bar(); (I'm rusty on C/C++, corrections welcomed).
public static void F()
{
String x = "original value";
FByValue(x);
Console.WriteLine(x);
FByReference(ref x);
Console.WriteLine(x);
}
public static void FByValue(String s)
{
s = "different value for local copy of parameter only";
}
public static void FByReference(ref String s)
{
s = "different value for caller's copy, thanks to ref keyword";
}
ref works only with parameters, never ever with fields; see MSDN for more detail.
Lastly: FByValue() and FByReference() would have identical semantics with int instead of String.

In C# there is a difference between value types and references.
First, there is nothing wrong with pointers in C/C++, that's how the language works and, that's how the hardware works as well. They can just be confusing to the new user.
In C#, the definition of structures and classes is different than C++:
if you define your data structures as struct or as class.
A struct is an object that gets copied around as it is passed from calls to calls. A class on the other hand gets its pointer passed around, similar to a C++ pointer, so if you have references to class instances in C#, you're really referencing the same object, and changes done at one place will be reflected everywhere you hold a reference to that object.

Related

Why should we initialize a struct before passing it to a function?

Consider this code:
MyStruct j;
j.I = 3;
Console.WriteLine(j.I);
Now see this method:
public static void StructMod(MyStruct ms)
{
ms.I += 100;
Console.WriteLine(ms.I);
}
When we pass MyStruct to the method, should we initialize it before passing it? I.e.:
MyStruct j = new MyStruct()
Unless struct is value type?
Yes, it is.
First line from MSDN:
A struct type is a value type...
As with individual variables, a struct must be fully initialized before it can be used. Consider:
struct Foo
{
public int Bar;
public int Pop;
}
class Program
{
static void Main(string[] args) {
Foo f;
f.Bar = 3;
test(f); // ERROR: Use of unassigned local variable 'f'
}
static void test(Foo f) {
Console.WriteLine("{0}", f.Bar);
}
}
The solution here is to either initialize .Bar, or simply call the Foo constructor f = new Foo() which initializes all members to their default values.
This is the same logic behind the "Field ... must be fully assigned before control is returned to the caller" error that you get when adding parameterized constructors to structs.
After a little testing, it seems that either way you declare it, it's being initialized.
One reason to call new ... would be to execute code in the constructor, if any.
Take this sample from MSDN, for example:
public struct CoOrds
{
public int x, y;
public CoOrds(int p1, int p2)
{
x = p1;
y = p2;
}
}
You could just do this, and use c, but then x and y will be 0.
CoOrds c;
Alternatively, you could do this, and then x and y start off with values.
CoOrds c = new CoOrds(5,3);
(This would be more useful if the ctor did something more interesting.)
If you want the struct to have a particular value, then initialize it to that value.
If you want the struct to be initialized to its default value, then you don't need to explicitly initialize it. However, it might still be best to do so for the sake of readability if the struct's default value is non-obvious.
As a side note: Mutable structs are really bad; the entire scenario you propose in your example is a code smell. See Why are mutable structs “evil”?
The same behavior could be achieved more safely with an immutable struct like so
struct MyStruct
{
public readonly int I;
public MyStruct(int i_initial)
{
I = i_initial;
}
}
MyStruct j = new MyStruct(3);
public static void StructMod(MyStruct ms)
{
Console.WriteLine(ms.I + 100);
}
In particular, note that from the caller's point of view this function's behavior will be exactly the same as the one in the question, because structs are passed by value the same way that primitives like int are. If the "Mod" in StructMod is there because you expect this function to modify the value, then that's a good concrete example of why it's generally better for mutable types to be objects and not structs.

Object pointers(object*) in C#

What I want to do is, I want to pass a pointer to a function that may be any type of a variable(int, long, string, even a class I mean I should be able to pass any variable's pointer). I'm doing this like that
unsafe class whatever
{
whatever(object* variable)
{
this.variable = variable;
}
}
ERROR IS: Cannot take the address of, get the size of, or declare a pointer to a managed type ('object')
Why I want to do is, I will store the variables passed through the constructor and will use their ToString() method, I'm trying to make a class that is for console applications, Refreshing the variables with their updated variables.
If I could do it like that My code will look like that
unsafe class whatever
{
whatever(object* variable)
{
this.variable = variable;
}
object* variable;
public override string ToString()
{
return *variable.ToString();
}
}
Maybe you should pass in a delegate that your class can use to obtain the “object string”.
class MyFancyClass
{
Func<string> getObjectString;
public MyFancyClass(Func<string> getObjectString)
{
this.getObjectString = getObjectString;
}
private MyOtherThread()
{
// ...
string desc = getObjectString();
// ...
}
}
// ...
long value = 34;
MyFancyClass fancy = new MyFancyClass(() => value.ToString());
// ...
value = 88;
// getObjectString() should now reflect the new value.
// The variable is captured in the lambdas closure.
Be careful though, because the delegate is called from another thread and simply calling ToString() may not be safe for all objects and require locking. However a delegate allows the caller to do this, depending on the object.
Pointers will get ugly, require unsafe code and aren't stable. The garbage collector can move objects around freely, if you don't explicitly make the pointers fixed. References can't be stored and you can only pass them around.
In C#, you usually don't use pointers. If you want to refer to a storage location, try this:
whatever(ref object variable)
{
}
Else, i would rather recommend using a wrapper class or another way to get to some variable.
A wrapper might look like this:
class Wrapper
{
public object Value { get; set; }
}
If you want to get the address of a variable it can't be a complex managed type. However, you can do something like this (assuming an unsafe context):
int a = 1;
IntPtr addr = ( IntPtr )( &a );
( * ( int* ) addr ) = 4;
a = 4;
Is this what you're looking for?
Edit:
If you're just wanting to save a "function pointer" from the object, just use a delegate to hold that.
class whatever
{
public whatever(object variable)
{
getVariableValue = variable.ToString;
}
Func<string> getVariableValue;
public override string ToString()
{
return getVariableValue();
}
}
void Main()
{
var type = new { F1 = "test", F2 = "value" };
whatever w = new whatever( type );
Console.WriteLine( w ); // This will invoke ToString
}
Output: { F1 = test, F2 = value }
You want a void* but becareful with those. if you make the wrong cast it will crash. it might be a wise idea to make a struct and cast to an intptr in this case.

C# Struct / Lookup Table

Say I have a struct declared like the following:
public struct Test
{
public static int Width = 5;
...
public static int[] Value = new int[1]{ 0 };
}
Now what I want to do is call this from within another struct, but I have to clue how. What I'm trying to do would (in my mind) look like the following:
public struct AnotherStruct
{
public (type of struct) this[int key]
{
get
{
switch(key)
{
case 1:
return (another struct);
default:
return null;
}
}
}
}
My end goal is that I want to use code that looks like the following, without having to create an instance of the object:
structobject s = new AnotherStruct[5];
So this 'lookup table' will be created in another project and built, then called as a dll from my main project. Since I'm building the dll elsewhere and calling it, I'm hoping that I can get the dll loaded into memory once, and then I can just reference that memory from my main project. Then I'll have one allocated portion of memory and my code will just reference it, avoiding the need to create individual instances of this lookup table (thus avoiding the time overhead it takes to allocate the memory and store the new instance). The time I'd save would be hugely beneficial in the long run, so I'm hoping I can get this to work somehow.
I hope this isn't too confusing, but let me know if any clarification is needed.
Edit
This is being used on a website, so really I need an object that persists across all connections and is created once when the code is initially loaded. Same idea, but maybe that will make for a simpler solution?
Solution #2. Forgo the whole ID idea and just use the structure type and generics.
public struct St1
{
}
public struct St2
{
}
public class Factory<T>
where T : struct
{
static T _new = new T(); //cached copy of structure
public static T New { get { return _new; } }
}
class Program
{
static void Main(string[] args)
{
St1 x1 = Factory<St1>.New;
St1 x2 = Factory<St1>.New;
St1 x3 = Factory<St1>.New;
St2 y1 = Factory<St2>.New;
St2 y2 = Factory<St2>.New;
}
}
Solution #1. Using a common interface for all the structures and a dictionary collection
public interface IStr { }
public struct St1 : IStr
{
public static int ID = 1;
}
public struct St2 : IStr
{
public static int ID = 2;
}
public class StructFactory : System.Collections.ObjectModel.KeyedCollection<int, IStr>
{
public static StructFactory Default = new StructFactory();
protected override int GetKeyForItem(IStr item)
{
FieldInfo finfo = item.GetType().GetField("ID",
BindingFlags.Static | BindingFlags.Public);
return (int)finfo.GetValue(item);
}
public StructFactory()
{
Add(new St1());
Add(new St2());
}
}
class Program
{
static void Main(string[] args)
{
St1 x = (St1)StructFactory.Default[1];
St2 y = (St2)StructFactory.Default[2];
}
}
The syntax you use above won't work since it means "create an array of AnotherStruct with five elements in it." As mentioned in a comment, however, you really should look into using a factory pattern.
However, if you really want to use the pattern above, you could change it up slightly. Have your AnotherStruct array hold Type instances of each of your structs. Then, your "creation" line would look more like:
structobject s = (structobject)Activator.CreateInstance(AnotherStruct[5]);
You can use reflection on the Assembly (since you are wrapping it in a DLL) to get those Type objects.
And finally, unless you have a really good reason for using struct (and understand all of the nuances, of which there are several), stick with class.

Meaning of "this" for a struct (C#)

According to MSDN (Section 11.3.6 of the C# spec):
Within an instance constructor of a
struct, this corresponds to an out
parameter of the struct type, and
within an instance function member of
a struct, this corresponds to a ref
parameter of the struct type. In both
cases, this is classified as a
variable, and it is possible to modify
the entire struct for which the
function member was invoked by
assigning to this or by passing this
as a ref or out parameter.
I don't get it. How is this different for a struct than for a class? Code examples are appreciated
Eric Lippert had a fabulous post on mutating readonly structs a while back that will really help clarify the issue for you. There's even a code example, and a quiz!
The salient point is that structs obey value semantics and classes do not and so this must mean something different for the two. this is readonly for a class, but not for a struct. The following code is legal
struct Point {
public int x;
public int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public void DoGoTime() {
GoTime(ref this);
}
public static void GoTime(ref Point p) {
p.x = 100;
p.y = 100;
}
}
but is not if "struct" is replaced by "class."
When you're dealing with structs, you're dealing with value types.
In a class, "this" is a reference to the current instance. This lets you mutate the class instance by setting properties/fields on the class.
However, if you're in a struct, things act differently. When you're in a struct's method, "this" lets you mutate the struct. However, if you're using this in a method, you're almost always dealing with a copy of the "original" struct.
For example:
struct Test
{
int i;
void Mutate() {
this.i += 1;
}
}
When you use this:
void MutateTest(Test instance)
{
instance.Mutate();
}
{
Test test = new Test();
test.i = 3;
Console.WriteLine(test.i); // Writes 3
test.Mutate(); // test.i is now 4
Console.WriteLine(test.i); // Writes 4
MutateTest(test); // MutateTest works on a copy.. "this" is only part of the copy itself
Console.WriteLine(test.i); // Writes 4 still
}
Now, the stranger part - this is valid, and what that quote was saying:
struct Test
{
public Test(int value)
{
this.i = value;
}
int i;
void Mutate(int newValue) {
this = new Test(newValue); // This wouldn't work with classes
}
}
///
{
Test test = new Test();
test.i = 3;
Console.WriteLine(test.i); // Writes 3
test.Mutate(4);
Console.WriteLine(test.i); // Writes 4
Jason's answer and Eric's post show one aspect of this which is interesting... but there's another which is even more alarming:
You can reassign this within a method, even if the type is otherwise immutable.
To demonstrate it, we'll use a struct which is stored in a non-readonly variable, but which contains a readonly field:
using System;
public struct LooksImmutable
{
private readonly int value;
public int Value { get { return value; } }
public LooksImmutable(int value)
{
this.value = value;
}
public void GoCrazy()
{
this = new LooksImmutable(value + 1);
}
}
public class Test
{
static void Main()
{
LooksImmutable x = new LooksImmutable(5);
Console.WriteLine(x.Value);
x.GoCrazy();
Console.WriteLine(x.Value);
}
}

How to pass references as arguments in a method in c#

How can you pass refernces in C#?
private void functionName (ref Type variableName)
{
}
To Call it
functionName(ref variable);
Your question is extremely unclear, but it's quite possible that my article on parameter passing in C# will answer whatever you really intended to ask.
In particular, you need to distinguish between passing a reference by value, and passing an argument by reference. If you're hazy on value types and reference types, you might also want to look at my article on that topic.
You can pass parameters by reference in C# using this syntax.
public void MyMethod(ref string myString)
{
}
You will then need to put ref before the value when passing it.
Jon Skeet has a good article on this here.
In C#, value types (like int, double, byte and structs) are passed by value, by default. This means that the receiving method has a NEW instance of the type. If an int that has a value of 1 is passed to the method, and the method changes it to 2, this change is only reflected within the method, the calling location's int is still 1. If however the ref keyword is added, then changes made to that integer are reflected back to the calling location.
All classes in C# are reference types. This means, by default, the references are passed by value. This is the important part. This means, changes made to that instance of the object are reflected back to the calling location, because it is the same object. However, if the method changes it's reference to a different object, this change is not reflected. In the case you want these changes reflected back, you would need to use the ref keyword on the parameter.
public static void Main()
{
int i = 1;
Method1(i); //i here is still 1
Method2(ref i); //i is now 2
SimpleObj obj = new SimpleObj();
obj.Value = 1;
Method3(obj); //obj.Value now 2
Method4(obj); // obj.Value still 2
Method5(ref obj); //obj.Value now 5
}
private static void Method5(ref SimpleObj obj)
{
obj = new SimpleObj();
obj.Value = 5;
}
private static void Method4(SimpleObj obj)
{
obj = new SimpleObj();
obj.Value = 5;
}
private static void Method3(SimpleObj obj)
{
obj.Value++;
}
private static void Method2(ref int i)
{
i++;
}
private static void Method1(int i)
{
i++;
}
public class SimpleObj
{
public int Value { get; set; }
}
The ref keyword is covered in section 10.6.1.2 of the C# 3.0 specification. Here is the msdn documentation.
Here is a nice overview of parameter passing in C#:
http://www.yoda.arachsys.com/csharp/parameters.html
Calling Code:
string companyName = "New Company";
GetEmail(ref companyName);
Method Code:
private void GetEmail(ref string companyName)
{
}
Your questions isn't clear, but I'd like to point out that in C#, objects are passed by reference by default. Meaning, if you have an object, and then pass that object on to a method that makes changes to that object, those changes will affect the object in your calling code as well, since they both reference the same object.

Categories

Resources