I would like to be able to assign values to list objects without directly referencing them:
Pseudo example:
List<int> intList = new List<int> { 0 };
???? intPointer = ref intlist[0];
*intPointer = 1; // I know * isn't possible here, but it is what I'd like to do
Console.WriteLine(intList[0]);
and it would output 1.
I'm thinking that this isn't possible, but I just wanted to make sure I wasn't missing anything.
Also, I'm not looking for an example that uses unsafe, I'm curious if this is possible in managed code.
C# doesn't have a concept of "ref locals" (the CLR does though). So you'll need to wrap the values in a reference type that you can mutate. For example,
public class Ref<T> where T : struct
{
public T Value {get; set;}
}
List<Ref<int>> intRefList = new List<Ref<int>>();
var myIntRef = new Ref<int> { Value = 1 };
intRefList.Add(myIntRef);
Console.WriteLine(myIntRef.Value);//1
Console.WriteLine(intRefList[0].Value);//1
myIntRef.Value = 2;
Console.WriteLine(intRefList[0].Value);//2
Edit: C# 7.0 added ref locals but they still can't be used in this way because you can't put ref locals into an array or list.
No, this is not possible in C#.
C# does not support references to local variables, which includes references to elements of local containers.
The only way to obtain a true reference in C# (that is, not an instance of a reference type, but an actual reference to another variable) is via the ref or out parameter keywords. Those keywords cannot be used with any sort of indexed value or property, which includes elements in a List<>. You also have no direct control over these references: the compiler performs the dereferencing for you, behind the scenes.
Interestingly, the CLR does support this kind of reference; if you decompile CIL into C# you will sometimes see types like int& that are references to int. C# purposely does not allow you to use these types directly in your code.
What you're asking is not possible when using a value type such as int. You'll need an additional level of indirection; You could wrap your integer for example.
See Mutable wrapper of value types to pass into iterators for an example of that.
Related
Intro
So far I am trying to wrap my head around structs. I have found many answers on the Topic "When to use a struct". Most of them are vague such as advice against the use of structs in general, with few exceptions. There are explanations of when to use structs (few examples):
immutable Data
value semantics as opposed to reference semantics
need them in code passing structured data to/from C/C++
Do not use structs unless you need them
But no example code as to when this case actually happens that it makes sense.
probably one of the most well known Questions/Answers is this one:
When should I use a struct rather than a class in C#?
Project structure
class StorageBlock<Type>:
/// this is a storage block. It is not a struct because the data is not immutable and it
/// should be passed by reference
public class StorageBlock<Type>
{
Type[] Data;
/* other stuff */
}
methodBlockSearcher():
public (StorageBlock<Type> FoundBlock, int FoundIndex) SearchBlock(Type searchForThisElement)
{
StorageBlock<Type> found = Blocks.Find(searchForThisElement);
int index = Array.IndexOf(found.Data, searchForThisElement);
return (found,index);
}
caller example:
(StorageBlock<Type> FoundBlock, int FoundIndex) searchResult = SearchBlock(searchElement);
/* process SearchResult(s) */
Questions
I wonder if it makes sense to convert (StorageBlock<Type> FoundBlock, int FoundIndex) searchResult to a struct. The search result should be immutable. It is only there to provide a return from specific indexing operations.
something like this:
struct BlockIndex
{
StorageBlock<Type> Block;
int Index;
}
Because a struct is a DataType, not a reference type, I also wonder if BlockIndex.Block (which is a class) will be a reference to the instance of block or a copy of the found block.
It seems like you're comparing structs to tuples (which are compiled to ValueTuple, not Tuple), not structs to classes (which is the more common question and the context of the original suggestions). Defining tuples with that syntax is a more recent construct in C# so I don't know that there is a best practice yet on whether to explicitly define a struct or use a tuple.
Behind-the-scenes, tuples are implemented as ValueTuple structs, so there should be minimal (if any) performance difference by defining a struct. It's more for coding convenience than performance.
As a pragmatist, I would say to continue using tuples until you have a measurable problem.
The search result should be immutable
This is the only thing I see that would make me consider defining a readonly struct, since ValueTuple is not immutable by default.
Because a struct is a [value type], not a reference type, I also wonder if BlockIndex.Block (which is a class) will be a reference to the instance of block or a copy of the found block.
It will still be a reference. Reference types do not cease to be reference types just because they're a property of a struct. The value of the reference will be carried along with the struct just like an integer would.
So I wanted to be able to mimic the "with" functionality of VB in C#, and came across a rather clever solution through StackOverflow:
public static x with<x>(this x item, Func<x,x> f)
{
item = f(item);
return item;
}
to implement you would do something like:
myObject = myObject.with(myVariable => {
//do things
});
However, I ran into a snag when I tried to implement this inside a struct with one of the struct's fields. It said that "anonymous methods [...] inside structs cannot access members of 'this' [...]."
I did some research on this and found an answer to this question, which states ultimately that "this" for value types cannot be boxed. After researching what boxing means for C#, it makes sense, considering that the parameter for the function doesn't have a defined type.
My question is, why can't "this" for value types be boxed?
The main point here is that for a method on a struct, the meaning of this is not a value (i.e. an value of your SomeStruct), but rather a reference (a ref SomeStruct, or effectively an in SomeStruct in the case of a readonly struct).
You can't box a managed pointer of this form - that isn't a scenario supported by the runtime. Managed pointers are only meant to be on the stack. In fact, currently you can't even have a ref SomeStruct field in a custom ref struct that can't escape the stack.
The compiler could cheat by pretending to do that - i.e. by dereferencing the managed pointer from a ref SomeStruct into a SomeStruct and creating a capture context where this is interpreted as "the SomeStruct that we dereferenced earlier", but ... then the compiler can't guarantee the same behaviours and outcomes (actually, I suspect a case could be made for this in the readonly struct scenario, but ... it is probably easier not to introduce that subtle distinction).
Instead, the compiler suggests that you effectively do the above step manually; since the compiler is no longer dealing in terms of this, it no longer has to pretend to respect the usual outcomes for dealing with this, and instead only has to guarantee the behaviours of an explicitly dereferenced copy of the value. That's why it advises (at least on current compiler versions):
Consider copying 'this' to a local variable outside the anonymous method, lambda expression or query expression and using the local instead.
Most lambdas, local methods, etc can therefore be achieved by the pragmatic step of:
MyStruct copy = this; // dereference
then in your lambda / local method / etc: instead of touching Something aka this.Something - touch copy.Something. It is now only copy that is being included in the capture-context, and copy is not bound by the ref SomeStruct rules (because: it isn't a ref SomeStruct - it is a SomeStruct).
It does, however, mean that if your intent was to mutate this (and have that visible in-place, rather than as a return value), then it won't work. You'll only be mutating the copy (i.e. copy). This is exactly what the compiler would have had to do anyway if it had lied, but at least now the copy step (dereference) is explicit and visible in your code.
I presume you know about setting properties during construction, which is similar (and more idiomatic of c#) ?
class MySpecialClass
{
public string Property1 {get;set;}
public int Length {get;set;}
public float Width {get;set;}
}
var p = new MySpecialClass
{
Property1 = "PropertyValue",
Length = 12,
OtherThing = 1.234F
};
How to create non-nullable value types like int, bool, etc. in C#?
Yes, these are called struct.
Structs are value types, just like int, bool and others.
They have some rules/recommendations related to them: (I think these are the most important)
a struct is passed and assigned by value, when not using ref or out keywords... this means that everything you put inside a struct will be copied when assigning or passing it to a method. That is why you should not make large structs.
you cannot define a parameterless constructor for a struct in C#
structs are better to be immutable, and have no property setters. You can get into real trouble by making mutable structs.
Other rules can be found within Microsoft docs about structs.
As for non-nullable reference types... this is not possible. You must check for nulls inside your code, manually.
7 years later and this is now possible
Install .NET Core 3.0 which includes C# 8.
Set the language version to 8.0: <LangVersion>8.0</LangVersion> to your .csproj file.
Add the property <NullableReferenceTypes>true</NullableReferenceTypes> (to your .csproj)
More details on his this affects writing code and your existing code here:
https://praeclarum.org/2018/12/17/nullable-reference-types.html
You can define a struct:
A struct type is a value type that is typically used to encapsulate small groups of related variables, such as the coordinates of a rectangle or the characteristics of an item in an inventory. The following example shows a simple struct declaration:
public struct Book
{
public decimal price;
public string title;
public string author;
}
However, you can't define aliases like int for System.Int32 and need to refer with the full name MyNamespace.Book (or Book with using MyNamespace;) to your struct.
English is not my mother tongue, exactly I am a Chinese. I'll be sorry if I cannot express my idea clearly.
I used to programme with c++. I really dont's understand the reference of C#.Many people tell me
the reference is similar to the pointer in c++.Such as below
Person Foo = new Person(); // C#
Person *Foo = new Person(); // C++.
Many times it works well.While many C# coders also tell me that the instance of class is just
the Foo.Foo has name.whiched is called Foo.name.Foo has age,which is called Foo.age. It seems the
thought is more easy to be used to code.But this thought does not conform to Memory model .
Please tell me What the reference is in c#.a object,or more likely a pointer?Thx.
You will want to get familiar with the different between Reference Type and Value Type.
Example is below:
void Main()
{
Foo A = new Foo{Age = 16}; //A creates a space in memory for the data of Foo and points to that memory location
Foo B = A; //B just creates a variable and points to the memory location created by A
A.Bar();
B.Bar();
//Result
//Your Age is 16
//Your Age is 16
A.Age = 24;
A.Bar();
B.Bar();
//Result
//Your Age is 24
//Your Age is 24 <----- B is pointing to the same location as A and reflects the changes on call.
FooValueType E = new FooValueType{Age = 23};
FooValueType F = E;
E.Bar();
F.Bar();
//Result
//Your Age is 23
//Your Age is 23
E.Age = 56;
E.Bar();
F.Bar();
//Result
//Your Age is 56
//Your Age is 23
}
public class Foo //These object are by reference
{
public int Age { get; set; }
public void Bar()
{
Console.WriteLine("Your Age is {0}", Age);
}
}
public struct FooValueType //These object are by value
{
public int Age { get; set; }
public void Bar()
{
Console.WriteLine("Your Age is {0}", Age);
}
}
C# has garbage collection and by default, it does not support pointers. You can however, use pointers as outlined here http://msdn.microsoft.com/en-us/library/t2yzs44b(v=VS.80).aspx
With respect to the variable behaviors, there are two kinds of types in C#:
Value types.
Reference types.
Value type variables carry the actual object as their value. Assigning a value type variable assigned from another value type variable copies the whole object. In C++ terms, this is like using a variable of the class type (not a pointer to the class) like for example when you're making a stack allocated instance. C# however doesn't give you that choice, but restricts this behavior only to such types as structs.
Reference type variables carry a reference to the actual object as their value. A reference to the actual object will most probably at least in involve the memory address of the object (but the details are hidden from you). Assigning a reference type variable from another reference type variable copies the reference, not the object, so now the two variables point to the same object. In C++ terms, this is like having a pointer variable of the class. C# however defaults to this behavior for variables of such types as classes and interfaces (and there's no way to jump back to the other behavior, as far as I know). The major difference between C# references and C++ pointers is that C++ pointers support arithmetic, while C# references don't. This is one of the ways C# ensures what we call memory safety. (C# does offer pointers, but they are used rarely and a lot of the time they are useful in interoperability scenarios. It'll likely be a long time before you ever need to use a pointer in C#.)
In the end, you can think that the C# reference is close to the C++ pointer (but, as outlined above, there are differences because the languages behave differently and give you different degrees of control and protection).
In C# when you say Person Foo = new Person();
new Person() creates an object of the class Person by allocating memory in heap section
returns a reference to this object (i.e nothing but reference to memory allocated) of type Person.
While Foo catches this reference and with this reference you can access the objects properties i.e its methods and variables.
In C++,
It follows the same steps but in c++ you catch a reference to object in a pointer of type Person.
More specifically new internally calls operator new function to allocate a memory dynamically to create objects.
In the image shown below Person p (on stack) creates an reference to an object returned by new Person().
age and name are the member variables of the Object.So we can easily access them using p.name and p.age.
More to add about stack and heap memory allocation in both c# and c++
The reference Foo always gets a memory on stack
Where object i.e here new Person() gets memory on heap and in case of C# more specifically it gets memory on managed heap
Updates
When you say new Person() it internally allocates memory for the Object Of the type -person.This object is composed of Persons members like shown in image.
You then can do two thing
Either you catch this reference in variable of type Person
e.g Person p = new Person();
Here p is a reference to memory location of object.So I can easily access Objects member using p.
Just don't store the reference directly use it e.g new Person().age will give me Persons age.This is called an anonymous Object.
Have you googled that before asking? There are many top resources on the internet and also some nice e-books.
However, here´s the memory model used in C# (in Java and PHP nearly as well):
Every object is inherited from the class object. That means, that nearly everything is an object in C#.
You don´t need to use pointer anymore. There´s nearly no need in C# for it. When you create an object, you will get back an reference to the instance in the stack. You could also have many references to one single object in stack. The references are located in the heap. This is the default behaviour and you aren´t able to change it, unless you do native code.
There´s no need of deleting something. It will be automatically happened by the Garbage Collector. It will be delete every local variable which is created inside a method at the end of it. The Garbage Collector will also delete objects, which got no reference anymore.
Internal datatypes are always located at the stack, strings also. For strings, they made an exception here, strings are also treated as simple datatypes, not as an object.
Every internal datatype will be copied per default, if you e. g. have give an int value to a method. This pattern is called "Call-By-Value". Every object will be passed by a new reference. That means, if you give an object as a method paremter, you will just get inside the method a new reference to the object. This pattern is called "Call-By-Reference". It´s very important, that you might divide in them.
You can change Call-By-Value to Call-By-Reference using the "ref" keyword. You could also define only an out parameter. That means, that doesn´t matter what value you give to a method. It will only return something at the end of the method. This can be done by using the "out" keyword in C#.
In logical conclusion to this, you are not able to overflow the heap in C#. Because the stack would get an overflow before...
There´s no difference anymore between static and object-calls. It´s always the dot. So, you could call public members of a class in the same way you would also call public static members of the class. For static members, you just need to use the class name, or inside the class without any keyword before the variable name. You call object/class member by using a reference to it.
You could only inherit from one class. Multiple inheritance is not supported it C# (Java and PHP as well).
Stdout commands (>> and >) changes to "Console" or to any other stream reference, e. g. file output streams.
Edit:
A child class inherits everything from the base class, also private and protected members/methods. But you can only access public and protected members/methods, unless you dont´ make use of reflections.
Hope, this helps you in order to unterstand C# a bit more...
The reference is a pointer to an object.
You can use "real" pointers in C# in unsafe code: here is an example
I am trying to port an existing c# to f# and would I am getting stuck on porting this c# line:
public object myInnerOject
In C# object is just a type name referring to System.Object. In F#, you can either use this full .NET name or a type alias obj.
Now, regarding a field declaration - there are various ways to write that depending on the context. Also, it is a good practice to initialize all fields in F#, so it would be useful to see larger context of your code.
However, you may write this:
type A() =
let mutable (myInnerObj:obj) = null
This creates a private field myInnerObj of type System.Object initialized to null, which is mutable can can be assigned later (myInnerObj <- new Random(), for example). I used example with private field, because public fields are generally discouraged in .NET.
#Tomas is right. You may also want to check out these blogs:
The basic syntax of F# - types
What does this C# code look like in F#?