I may sound stupid question to you, but I really want to know it.
in Entity Framework (EF) on context class DbSet when we call Add(object) method , how it update the Id column on entity. I mean if its using "REF" and "OUT" we can understand how it update the ID field but here without using REF and OUT how it can under the object property.??
//model.ID -- here its zero
context.Entry(model).State = EntityState.Added;
context.SaveChanges();
//model.ID -- here its no zero
This is explained much more thoroughly in the C# documentation types, but here the gist of it:
Value types are items like int, bool, any struct, etc. These are blocks of memory that hold a distinct value.
Reference types are items like string, object, any class, etc. These are actually just 'references' to the block of memory holding their value.
If you pass a value type as a parameter to a method, then that value is essentially copied into a new block of memory and the original value cannot be modified by the code in the method.
public static void Main()
{
int myInt = 5;
Console.WriteLine(myInt);
ChangeMe(myInt);
Console.WriteLine(myInt);
}
public static void ChangeMe(int i)
{
i = 7;
}
// Outputs:
// 5
// 5
In order to modify a value type, you have to use the "ref" or an "out" parameter.
public static void Main()
{
int myInt = 5;
Console.WriteLine(myInt);
ChangeMe(ref myInt);
Console.WriteLine(myInt);
}
public static void ChangeMe(ref int i)
{
i = 7;
}
// Outputs:
// 5
// 7
This, however, does not apply to types that are already reference types. Typically, in entity framework you work with types that are set up as class objects. These are reference types by default. Passing a reference type to a method does not 'copy' it like a value type does, the method instead gets access to the original object. This is because you are merely passing a location to where that memory lives. This manifests in allowing the method to modify the values on the class.
public class MyClass
{
public int MyInt { get; set; }
}
public static void Main()
{
MyClass myclass = new MyClass();
myclass.MyInt = 5;
Console.WriteLine(myclass.MyInt);
ChangeMe(myClass);
Console.WriteLine(myclass.MyInt);
}
public static void ChangeMe(MyClass i)
{
i.MyInt = 7;
}
// Outputs:
// 5
// 7
Related
I am able to update private members of a class instance from main method of other class. why was I allowed to do that. Is it like, its the use of "ref" keyword?
I tried modifying using "ref" keyword.
using System;
namespace Test2
{
class A
{
private int a=10;
public ref int M()
{
return ref a;
}
virtual public void display()
{
Console.WriteLine("class A");
}
}
class B:A
{
}
class Program
{
static void Main(string[] args)
{
B b = new B();
ref int a = ref b.M();
Console.WriteLine(a);
a = 20;
Console.WriteLine(b.M());
Console.ReadKey();
}
}
}
When you return a ref, that means "the caller gets to make an alias for the variable I have returned."
If that variable is private, that doesn't matter. The caller gets to make an alias for that variable; if you didn't want the caller to do that, you should not have given them that ability!
Remember, privacy is only about names. a is private, so the name a may only be used from within that class. That is all that private means. It does not mean that the variable may not be changed; it means that the variable cannot be identified by that name outside of the class.
In your example, you are not identifying the variable being modified by its name in the class. You're identifying it by its alias, which is the local variable a.
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/ref-returns
A.M() returns a reference for A.a and you assign that reference to the variable a, which is not the value of A.a but a reference to A.a.
So, assigning a value to a is assigning a value to A.a.
C# has types by reference and types by value
Types values are primitive tipes like int, float, double and when you pass it to a method you really pass the value, so is like pass a copy of the object.
The keyword ref modifies this behavior and pass the reference to the object, the memory address of a value not value, so when you modified the value affects all the classes that have a reference to it, the value is the same in all
Please take a look:
ref keyword
I read this answer: https://stackoverflow.com/a/9928643/16241
But I obviously don't understand it because I can't figure out why my method is impure. (The method in question is ToExactLocation()).
public struct ScreenLocation
{
public ScreenLocation(int x, int y):this()
{
X = x;
Y = y;
}
public int X { get; set; }
public int Y { get; set; }
public ExactLocation ToExactLocation()
{
return new ExactLocation {X = this.X, Y = this.Y};
}
// Other stuff
}
Incase you need it here is the exact location struct:
public struct ExactLocation
{
public double X { get; set; }
public double Y { get; set; }
// Various Operator Overloads, but no constructor
}
And this is how I call it:
someScreenLocation = MethodThatGivesAScreenLocation();
if (DestinationLocation == someScreenLocation.ToExactLocation())
{
// Do stuff
}
When I do that, ReSharper flags it with "Impure Method is called for readonly field of value type."
Why is it saying that? And what can I do to make it go away?
It's not pure because it does not return a value dependent only on its input. When the value of X or Y changes so does the return value of ToExactLocation, i.e., its output depends on internal, mutable state.
Additionally, the setters for X or Y in ExactLocation may mutate the input. The getters of ScreenLocation may as well.
someScreenLocation is a readonly field and is a value type. You are calling ToExactLocation on a value, i.e., a readonly field. When you access a reaodnly value type a copy is created as to avoid mutating the value itself. However, your call may mutate that value, which, in many cases, is not what you want as you will be mutating a copy. This is why you get a warning.
In this case, you can ignore it, but I would avoid mutable value types in general.
EDIT:
Let me attempt to simplify...
struct Point
{
int X;
int Y;
bool Mutate() { X++; Y++; }
}
class Foo
{
public readonly Point P;
Foo()
{
P = new Point();
P.Mutate(); // impure function on readonly value type
}
}
When Mutate() is called, a copy of P is created and passed along with the method. Any mutation of P's internal state will be irrelevant as it mutates a copy.
One of the conditions of a Pure Method is that its output (return value) is wholly dependent on its input (arguments).
Your .ToExactLocation() method is not pure, because its output depends both on the input arguments and also on the current value of a mutable struct.
Resharper doesn't like this, because mutable structs are bad (don't use them). I expect the error would go away if you either changed your code to use a class instead of a struct or redesigned the struct so the the .X and .Y members could only be set by the constructor.
Reading the answer, I found out that pure functions are necessarily like functions in mathematics. f(x) = x^2 + 2x + 10 will always return 10 if x is 0.
So ToExactLocation() must return the same values each time it is called, regardless changes to object since initial creation, for it to be called "pure".
There are 2 meaning of "pure function": one theoretical (no side effects/no dependency on mutable state) and another is what ReSharper thinks about functions.
From theoretical point of view your function is not pure because it depends on mutable state. Sample:
var someScreenLocation = new ScreenLocation(1,1);
var locationOne = someScreenLocation.ToExactLocation();
var locationTwo = someScreenLocation.ToExactLocation();
someScreenLocation.X = 3;
var locationThree = someScreenLocation.ToExactLocation();
For method to be pure it can change its result only based on input (not at all as in this case since there is no arguments). But you can clearly observe that locationOne and locationTwo are the same (good sign so far), but unfortunately locationThree is different even if the input (arguments to the function) still the same.
You can make it theoretically pure by making X and Y readonly (and adding constructor).
Even after the change ReSharper will still think it is not pure - to convince it you can use Pure attribute to mark it as pure.
Note that ReSharper marks usage of "impure" functions even in constructor of the class with readonly field. Sample below shows ReSharper warnings:
struct Point
{
public int X;
public int Y;
public Point(int x, int y){X = x;Y = y;}
public void Mutate(){X++;}
public Point TheoreticallyPure(){return new Point(1, 1);}
[Pure] public Point MarkedPure(){ return new Point(1, 1);}
}
class WithReadonlyField
{
public readonly Point P;
public WithReadonlyField()
{
P = new Point();
P.TheoreticallyPure(); // impure function on readonly value type
P.MarkedPure(); // return value of pure not used
P.Mutate(); // impure function on readonly value type - modifies P.
P = new Point().MarkedPure(); // ok to modify P multiple times.
}
public void NormalMethod()
{
P.Mutate(); // impure function on readonly value type, no changes to P
}
}
C# allows modification of readonly fields up to the end of constructor, but ReSharper marks usages of all "impure" functions there too (Note that Mutate function in constructor actually changes value of readonly field P, unlike in NormalMethod where it has no effect).
"readonly... assignments to the fields introduced by the declaration can only occur as part of the declaration or in a constructor in the same class"
Most likely this behavior of ReSharper is for consistency and to avoid cases where moving perfectly valid code changes behavior completely.
It would be better to model this as a static method (on either class) and would get rid of the impure warning. Explanation omitted, as the other answers covers the why already.
Example:
public static ExactLocation ToExactLocation(ScreenLocation loc)
{
return new ExactLocation {X = loc.X, Y = loc.Y};
}
or use an extension method
public static ExactLocation ToExactLocation(this ScreenLocation loc)
{
return new ExactLocation {X = loc.X, Y = loc.Y};
}
Not really sure about the cause, and I'd put this as a comment if it would format correctly...
Wouldn't you want something like:
var someScreenLocation = MethodThatGivesAScreenLocation();
if (DestinationLocation.X == someScreenLocation.ToExactLocation().X &&
DestinationLocation.Y == someScreenLocation.ToExactLocation().Y)
{
// Do stuff
}
Say I have a simple class like this:
public class ReferenceChanger<T>
{
public T SavedElement { get; private set; }
public ReferenceChanger(T elementToSave)
{
SavedElement = elementToSave;
}
// This method would change the original variable (given as a constructor argument)
public void SetNewReference(T newElement)
{
SavedElement = newElement;
}
}
This class saves an element given to its constructor, whatever element is. However, the "SavedElement" (its backing field) is a reference to the object given at the time of instance creation.
Is there any way to save a reference to a variable (as with using ref keyword), so that if the original item passed to the constructor changes, the SavedElement would automatically reflect the change, almost as if the object was passed with the ref keyword? (Even if I use the ref keyword, I would not be able to save the reference that way.)
Updated to make intentions more clear:
public class ExampleClass
{
public List<int> Numbers { get; set; }
}
public static void Main()
{
ExampleClass temp = new ExampleClass();
temp.Numbers = new List<int>() { 1, 2, 3 };
ReferenceChanger<List<int>> changer = new ReferenceChanger<List<int>>(temp.Numbers);
// Here, a reference to the List<int> instance (containing 1,2,3) is stored in changer's SavedElement
// Then I do this:
changer.SetNewReference(new List<int>() { 5, 6, 7 });
// Now, only changer's SavedElement was changed, but temp's property Numbers was not changed.
// Is there a way to change the temp's property Numbers from the changer?
}
Sounds like you're looking for TypedReference and the __makeref keyword.
Warning: they're poorly documented and not in the standardized part of C#.
There's a lot more information in this question.
All classes in C# are reference objects so what you have coded should update the value of SavedElement. However, if T is a primitive type (e.g., int, string, etc.), this would not work since these are set by value. You would need to put a constraint on T to make sure it's a class.
You cannot normally capture a reference to a variable and store it as a property. One hackish solution (not really suggesting it's a good idea, I'd explore other avenues first) is to capture it in a closure and pass the closure around. Closures capture variables, not values. As a result, changes to variables can be observed elsewhere. For example, given
class Foo
{
public int Baz { get; set; }
}
class Bar
{
private Func<Foo> fooGetter;
public Bar(Func<Foo> fooGetter)
{
this.fooGetter = fooGetter;
}
public void Do()
{
Console.WriteLine(fooGetter().Baz);
}
}
You can have
Foo foo = new Foo() { Baz = 1 };
Bar bar = new Bar(() => foo);
bar.Do();
foo = new Foo() { Baz = 2 };
bar.Do();
Changes to the variable foo are observed, since that is what the caller enclosed in the lambda. Had the caller simply said () => new Foo(), you would (of course) not observe any changes.
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 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.