Save a object reference for future usage using ref keyword - c#

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.

Related

Anonymous type with var gives error CS0825 [duplicate]

This question already has answers here:
Implicit typing; why just local variables?
(6 answers)
Closed 1 year ago.
I want to create an anonymous type in C# inside a class.
The examples I have seen use var to create an anonymous variable
var RecordId = new
{
Foo = 0,
Bar = "can be also a string"
};
However I want to create my anonymous variable inside a class.
public class Logger //: LogBase
{
var RecordId = new
{
Foo = 0,
Bar = 1
};
}
So when Logging I can do:
Logger.RecordId.Foo
But declaring my anonymous type as var triggers the following error:
CS0825: The contextual keyword 'var' may only appear within a local variable declaration.
What is the type of an anonymous variable, so I don't have to use var?
I understand what the error is telling me, but I don't want to move my variable inside a function, it needs to be a property of Logger.
Edit: enum is what I tried t the beginning, but I need the values to be more flexible than just integers (like strings, so I can dump jon files).
I updated my question to reflect that.
var (and by definition anonymous types) can only be declared inside a method, the error message is basically telling you that. If you need this type to be at class level, then make a class/struct/tuple to store it.
public static class Record
{
public static int Foo { get; set; }
public static int Bar { get; set; }
}
public class Logger //: LogBase
{
public static Record RecordId { get; set; } = new Record();
}
Now you can do this:
var foo = Logger.RecordId.Foo;
Note that I also used static so you don't need to create a new instance of the class, but change that if you think it's relevant.
public class Logger //: LogBase
{
public enum RecordId
{
Foo = 0,
Bar = 1
}
}
If you do not want strings you can do the above.
public class LogCategory
{
private LogCategory(string value) { Value = value; }
public string Value { get; private set; }
public static LogCategory Foo { get { return new LogCategory("Foo"); } }
public static LogCategory Bar { get { return new LogCategory("Bar"); } }
}
If you want strings you could create your own class something like the above.
You can use the dynamic type to have an anonymous instance variable.
public class Foo
{
dynamic bar = new {
A = 1,
B = 2
};
public void Print() {
Console.WriteLine(bar.A);
}
}
Try it out!
Just because you can do this doesn't mean it's a good idea. See DavidG's answer for an alternative using a strongly-typed object that will not require you to expose your code to the many problems associated with the dynamic type.

How are C# 6.0 default property values assigned and affected by scope when using function calls?

I might get some downvotes here, but I've actually found conflicting information through normal searches and would like a definitive answer other people can also easily find.
Given a property in current C#:
public static IEnumerable<string> foo { get; set; } = new string[] { "bar", "bar2" };
We know that the default value of foo will return as the above array. If another value is assigned, the default value is no longer used. However, what if the case is :
public static IEnumerable<string> foo { get; set; } = GetMyStrings();
My thought is that this functions like:
if(foo == null) { foo = GetMyStrings();}
and that foo will retain the value from its first run of GetMyStrings() for the lifetime of the object unless overwritten by a manually assigned value.
My colleague insists this risks a GC problem, and that the result of GetMyStrings() can fall out of scope and be collected, "renullifying" the parameter and causing multiple calls to GetMyStrings() over the lifetime of the object.
Which of us is correct?
No, actually it is like this:
static ClassName()
{
foo = GetMyStrings();
}
The compiler generates a static constructor and puts the assignment call in there (just like it creates a line in the constructor for non-static properties).
My colleague insists this risks a GC problem, and that the result of GetMyStrings() can fall out of scope and be collected, "renullifying" the parameter and causing multiple calls to GetMyStrings() over the lifetime of the object.
He is talking nonsense. An assigned instance will never be garbage collected, no matter from where exactly it was assigned.
Writing this
public static IEnumerable<string> Foo { get; set; } = GetMyStrings();
is syntactic sugar over this declaration
public static IEnumerable<string> Foo { get; set; }
and an addition of static constructor that looks like this:
static MyClass() {
Foo = GetMyStrings();
}
(if you already have a static constructor, Foo = GetMyStrings(); line is added to it implicitly).
Other than that, there is no difference: once it is time for the class to get initialized, GetMyStrings() is called from the constructor, then the value it returns is assigned to Foo. After that the value remains there until it is replaced by another one, or the program ends.
As far as "renullifying" the parameter goes, it never happens to the same instance of the class object. You can get multiple calls to GetMyStrings() when app domain containing the class gets unloaded, or when the class is loaded into another app domain, but that has nothing to do with the new C# 6 syntax.
Finally, if you do not plan to change Foo after the static constructor, consider making it read-only:
public static IEnumerable<string> Foo { get; } = GetMyStrings();
To exemplify my comment, look at this example:
public void RunTest()
{
Test t = new Stackoverflow.Form1.Test();
Console.WriteLine(t.Values.First());
System.Threading.Thread.Sleep(1000);
Console.WriteLine(t.Values.First());
System.Threading.Thread.Sleep(1000);
Console.WriteLine(t.Values.First());
Console.WriteLine("------");
Console.WriteLine(t.Values2.First());
System.Threading.Thread.Sleep(1000);
Console.WriteLine(t.Values2.First());
System.Threading.Thread.Sleep(1000);
Console.WriteLine(t.Values2.First());
Console.WriteLine("------");
Console.WriteLine(t.Values3.First());
System.Threading.Thread.Sleep(1000);
Console.WriteLine(t.Values3.First());
System.Threading.Thread.Sleep(1000);
Console.WriteLine(t.Values3.First());
}
public class Test
{
public IEnumerable<string> Values { get; set; } = GetValues();
public static IEnumerable<string> GetValues()
{
List<string> results = new List<string>();
for (int i = 0; i < 10; ++i)
{
yield return DateTime.UtcNow.AddMinutes(i).ToString();
}
}
public IEnumerable<string> Values2 { get; set; } = GetValues2();
public static IEnumerable<string> GetValues2()
{
return GetValues().ToList();
}
public IEnumerable<string> Values3 { get; set; } = GetValues().ToList();
}
The output from this is:
19/04/2017 12:24:25
19/04/2017 12:24:26
19/04/2017 12:24:27
------
19/04/2017 12:24:25
19/04/2017 12:24:25
19/04/2017 12:24:25
------
19/04/2017 12:24:25
19/04/2017 12:24:25
19/04/2017 12:24:25
Values: As you can see, the IEnumerable<> from the method using yield will be evaluated each time you call it.
Values2: The method returns a List. Since List implements IEmnumerable, you're still just returning the concrete instance of List (albeit presented as its IEnumerable interface) and thus it only gets evaluated once.
Values3: We've basically moved the .ToList() outside of the GetValues2() method and just implemented it directly on the property. The result here is the same as Values2, for basically the same reason.
When you return a concrete object that implements IEnumerable, it will be evaluated once, but watch out for the first example.
And remember folks, Linq is a view. if the underlying data changes, so does what's returned from your Linq expression.
Re the garbage collection question: Objects that are referenced by an active object will not be garbage collected.

Readonly getters VS property-like functions

With C#6 came some new features, including getter-only auto-properties and property-like function members.
I'm wondering what are the differences between these two properties? Is there any reason why I'd prefer one to another?
public class Foo
{
public string Bar {get;} = "Bar";
public string Bar2 => "Bar2";
}
I know that {get;} = can only be set by a static call or a constant value and that => can use instance members. But in my particular case, which one should I prefer and why?
It's easiest to show them in terms of C# 1:
public class Foo
{
private readonly string bar = "Bar";
public string Bar { get { return bar; } }
public string Bar2 { get { return "Bar2"; } }
}
As you can see, the first involves a field, the second doesn't. So you'd typically use the first with something where each object could have a different state, e.g. set in the constructor, but the second with something which is constant across all objects of this type, so doesn't need any per-object state (or where you're just delegating to other members, of course).
Basically, ask yourself which of the above pieces of code you would be writing if you didn't have C# 6 available, and choose the corresponding C# 6 path.

EF Add method Identity Column value

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

C# - How to access a static class variable given only the class type?

This is my first time posting on Stack Overflow, so hopefully I did everything right and you guys can help.
I'm wondering if in C# there's a way to access a static variable belonging to a class, when given only the type of the class. For example:
public class Foo
{
public static int bar = 0;
}
public class Main
{
public void myFunc(Type givenType)
{
int tempInt = ??? // Get the value of the variable "bar" from "Foo"
Debug.WriteLine("Bar is currently :" + tempInt);
}
}
// I didn't run this code through a compiler, but its simple enough
// that hopefully you should get the idea...
It's hard to describe the context of needing to know this, but I'm making a game in XNA and I'm trying to use reference counting to reduce the complexity of the design. I have objects in the game and power-ups that can apply an effect them (that stays on the objects). Power-ups can die but their effects can still linger on the objects, and I need to keep track of if any effects from a power-up are still lingering on objects (thus, reference counting). I plan to make a "PowerUpEffect" class (for each type of power-up) with a static integer saving the number of objects still affected by it, but the design of the rest of the game doesn't work well with passing the PowerUpEffect all the way down to the object for it to call a method of the PowerUpEffect class.
I'm hoping to pass only the PowerUpEffect's type (using something like "typeOf()") and use that type to reference static variables belonging to those types, but I have no idea how to do it or if it's even possible.
I'd be glad to even find work-arounds that don't answer this questions directly but solve the problem in a simple and elegant design. =)
Help! (and thanks!)
If you only have the Type handle, you can do this:
var prop = givenType.GetProperty("bar");
var value = prop.GetValue(null);
I would use a Dictionary instead, which are probably the most concise way of mapping one set of values to another. If you are associating int values with Types, then do something like:
public static readonly Dictionary<Type, int> sTypeValues =
new Dictionary<Type, int>
{
{ typeof(Type1), 5 },
{ typeof(Type2), 10 },
{ typeof(Type3), 2 },
{ typeof(Type4), 3 },
{ typeof(Type5), -7 }
};
your function then becomes:
public void myFunc(Type givenType)
{
int tempInt = sTypeValues[givenType];
Debug.WriteLine("Bar is currently :" + tempInt);
}
int tempInt = (int) givenType.GetField("bar").GetValue(null);
Okay, so you have a collection of powerups, and you want to have an integer associated with each of those powerups. Rather than having a lot of classes, each with a static integer, you can have a single static collection which holds onto all of the powerups and their associated integer values.
public static class MyPowerupInfo
{
public static Dictionary<PowerUp, int> PowerUps {get; private set;}
static MyPowerupInfo
{
PowerUps = new Dictionary<PowerUp, int>();
PowerUps.Add(*some power up object goes here*, 0);
//TODO add other power ups
}
}
Then to use it you can do something like:
int powerupCount = MyPowerupInfo.PowerUps[wickedAwesomePowerup];
or:
public static void IncrementPowerup(Powerup powerup)
{
MyPowerupInfo.PowerUps[powerup] = MyPowerupInfo.PowerUps[powerup]+1;
}
If am getting you correc, this might give you some idea:
using System;
using System.Reflection;
public class RStatic
{
private static int SomeNumber {get; set;}
public static object SomeReference {get; set;}
static RStatic()
{
SomeReference = new object();
Console.WriteLine(SomeReference.GetHashCode());
}
}
public class Program
{
public static void Main()
{
var rs = new RStatic();
var pi = rs.GetType().GetProperty("SomeReference", BindingFlags.Static | BindingFlags.Public); // i have used GetProperty in my case
Console.WriteLine(pi.GetValue(rs, null).GetHashCode());
}
}
Are you assuming if the name of the field you're trying to access (for example, for the class "foo", the field "bar") is a different field based on the Type parameter?
If the name of the field is known based on a finite number of allowable types, you should be able to determine it with a switch statement. For example:
public class Foo
{
public static int bar = 0;
}
public class Baz
{
public static int bing = 0;
}
public class Main
{
public void myFunc(Type givenType)
{
switch (givenType.ToString())
{
case "Foo":
Debug.WriteLine("Bar is currently :" + Foo.bar);
break;
case "Baz":
Debug.WriteLine("Bing is currently :" + Baz.bing);
break;
}
}
}

Categories

Resources