I'm trying to implement behavior similar to that of the GameObject in Unity3D.
I have many, many objects in any given application that reference any given number of other objects. Each object can be marked for deletion, and when it is; I need to know how to nullify any references to it so that it can be collected by the GC and literally removed from scope altogether. I'm either looking for a way to fake this or a way of actually doing it.
For all intents and purposes; if an object references another, and the referenced object is destroyed, I need the reference to appear to be null. If I can't do this then my only other option is to check every reference, every time I use them, and manually evaluate whether it's been destroyed, which isn't practical.
There are two approaches that I know of which come close to what you described:
Approach 1: WeakReference
Only use WeakReference to reference to objects except for one 'DataManager' that retains a hard reference.
You can then 'mark' instances for garbage collection by clearing the hard reference of the DataManager.
public class DataManager
{
private readonly HashSet<object> data = new HashSet<object>();
public void RegisterInstance(object instance)
{
data.Add(instance);
}
public void FreeInstance(object instance)
{
data.Remove(instance)
}
}
public class Foo
{
List<WeakReference<Bar>> bars = new List<WeakReference<Bar>>();
private readonly DataManager dataManager;
public Foo(DataManager dataManager)
{
this.dataManager = dataManager;
}
public void LogSomething()
{
bars.Add( Bar.Create(dataManager, 3, "Susan"));
bars.Add( Bar.Create(dataManager, 4, "Bob"));
bars.Add( Bar.Create(dataManager, 0, "Megan"));
dataManager.FreeInstance(bars[1]);
CG.Collect();
for(int i = bars.Count - 1; i >= 0; i--;)
{
// hard reference to not loose the reference target between now and logging
Bar bar;
if(!bars[i].TryGetTarget(out bar)
{
bars.RemoveAt(i);
continue;
}
Debug.Log($"{bar.value.Data2} has {bar.value.Data1} chocolate bars");
}
}
}
public class Bar
{
public int Data1 { get; private set; }
public string Data2 { get; private set; }
private Bar(int data1, string data2)
{
Data1 = data1;
Data2 = data2;
}
public static WeakReference<Bar> Create(DataManager dataManager, int data1, string data2)
{
var bar = new Bar(data1, data2);
dataManager.RegisterInstance(bar);
return new WeakReference(bar);
}
}
Cons
Weak references will continue to point to the target that was marked for deletion until it is actually garbage collected.
Running the garbage collector after each deletion isn't a very good idea
It's slow
Garbage collector might not even collect it. Meaning that a WeakReference can suddenly lose reference between two lines of code some time after deletion. This requires you to keep a hard reference everytime that you have to access the target of a weak reference more than just once.
You have to register every created object in the DataManager.
It's very easy to forget to use WeakReference to reference to objects.
Approach 2: Use a wrapper
You can wrap all your objects in a generic class and only reference the wrapper, but you have to use the same wrapper for every object of T.
So you will need some kind of DataManager like in approach 1.
public class Wrapper<T>
{
public T Value { get; private set; }
public Wrapper(T value)
{
Value = value;
}
public void Delete()
{
if(Value == null)
throw new InvalidOperationException("Already deleted");
Value = null;
}
public static implicit operator T(Wrapper<T> wrapper) => wrapper.value;
public static implicit operator Wrapper<T>(T x) => new Wrapper(x);
}
public class Foo
{
List<Wrapper<Bar>> bars = new List<Wrapper<Bar>>();
public void LogSomething()
{
bars.Add( new Bar(3, "Susan"));
bars.Add( new Bar(4, "Bob"));
bars.Add( new Bar(0, "Megan"));
bars[1].Delete()
for(int i = bars.Count - 1; i >= 0; i--;)
{
var bar = bars[i];
if(bar.value == null)
{
bars.RemoveAt(i);
continue;
}
Debug.Log($"{bar.value.Data2} has {bar.value.Data1} chocolate bars");
}
}
}
public class Bar
{
public int Data1 { get; private set; }
public string Data2 { get; private set; }
public Bar(int data1, string data2)
{
Data1 = data1;
Data2 = data2;
}
}
You could also overwrite the equals method of Wrapper to achieve the following behavior:
var bar = new Wrapper<Bar>(null);
var isWrappedValueNull = bar == null;
// overwrite 'equals' if you want isWrappedValueNull to be true in this case
I wrote this with the android app - example code might have minor errors
You can't set this (aka 'yourself') to null so that references to you will be lost / destroyed. this is read-only.
Something you can do is using events to tell the ones referencing the instance to set it to null. Don't forget to unsubscribe the event handler when setting the instance to null.
Related
There are quite a few posts about thread-safe changes to a ConcurrentDictionary, however, all of the examples I have searched concern themselves with changing the whole value. I think this is a slightly different question..
I'm after some guidance on the best way to change a property of an object value already in a ConcurrentDictionary?
For example, I could do the following but not sure if it's thread-safe
CustomObject obj;
if (customObjectDictionary.TryGetValue(objectKeyToChangeProperty, out obj))
{
obj.Property2 = "NewData";
}
Another way is to copy the dictionary using ToArray and then get the required object, amend the property and then use the thread-safe AddOrUpdate method
obj = customObjectDictionary.ToArray().Select(x => x.Value).FirstOrDefault();
if(obj != null)
{
obj.Property2 = "NewData";
customObjectDictionary.AddOrUpdate(obj.Key, obj, (oldkey, oldvalue) => obj);
}
This seems a bit of a long winded way of doing this and not sure if calling ToArray will be performant if doing this many times.
Sample Code is below:
public partial class Form1 : Form
{
private ConcurrentDictionary<int, CustomObject> customObjectDictionary { get; set; }
public Form1()
{
InitializeComponent();
InitialzeObjects();
Start();
}
private void InitialzeObjects()
{
customObjectDictionary = new ConcurrentDictionary<int, CustomObject>();
var o1 = new CustomObject() { Key = 1, Property1 = 1, Property2 = "Object1" };
customObjectDictionary.AddOrUpdate(o1.Key, o1, (oldkey, oldvalue) => o1);
var o2 = new CustomObject() { Key = 2, Property1 = 2, Property2 = "Object2" };
customObjectDictionary.AddOrUpdate(o2.Key, o2, (oldkey, oldvalue) => o2);
}
private async void Start()
{
bool complete = await Task.Run(() => Test());
}
private async Task<bool> Test()
{
int objectKeyToChangeProperty = 2;
CustomObject obj;
// Method 1 change local variable directly
if (customObjectDictionary.TryGetValue(objectKeyToChangeProperty, out obj))
{
obj.Property2 = "NewData";
}
// Method 2 - make copy first then
obj = customObjectDictionary.ToArray().Select(x => x.Value).FirstOrDefault();
if(obj != null)
{
obj.Property2 = "NewData";
customObjectDictionary.AddOrUpdate(obj.Key, obj, (oldkey, oldvalue) => obj);
}
return true;
}
}
public class CustomObject
{
public int Key { get; set; }
public int Property1 { get; set; }
public string Property2 { get; set; }
}
A concurrent collection is thread safe in the respects that it will always be internally consistent, even if it's at the cost of you getting snapshots of the collection (among other trickery). However, and it's a big however, the objects inside the collection or the code you write that use it are not guaranteed to be thread safe.
I'm not sure of the actual problem you are trying to solve or the threading nature of properties you are trying to change. Though, the safest bet (and if you are unsure) is to just use a lock when accessing these properties.
It is not safe, so you must protect it somewhere else.
There are multiple patterns and that will depend on the current scenario.
For example, if you need to increment a variable:
if (customObjectDictionary.TryGetValue(objectKeyToChangeProperty, out obj))
{
obj.Property1++;
}
behind the scene you are reading Property1, adding 1, and save it again in one line, but not in an atomic instruction, in the middle it could have change 50 times.
you can protect thta code with a lock, inside the if, but another developer can come 2 years later and do the same somewhere else, and not realize that he/she is forgetting the lock
Then you could enforce the read and write inside the object that locks, foe example:
public class CustomObject
{
private int _Property1;
public Property1
{
get
{
return _Property1;
}
public void IncrementProperty1By (int increment)
{
lock { ... Property1++ ... }
}
}
I have a class with some static filds. When they are initialised they add themself to a Dictionary.
When the program starts a second time it tries to access the content of the Dictionary but since I haven't accessed any filds in the class (the Dictionary is in another) they can't be found.
I already understand that the static fields are initialised when I access one of them but are there any other ways to initialise them without calling any methods or fields for no other reason then nitialising them once?
----------------------
Here some code:
Resource.cs
public class Resource : InventoryItem
{
public const int IDBase = 1000000;
private Resource(int id) : base(IDBase + id) { }
public static Resource Hydrogen { get; } = new Resource(1); // H
public static Resource Helium { get; } = new Resource(2); // He
public static Resource Lithium { get; } = new Resource(3); // Li
public static Resource Beryllium { get; } = new Resource(4); // Be
public static Resource Boron { get; } = new Resource(5); // B
public static Resource Carbon { get; } = new Resource(6); // C
public static Resource Nitrogen { get; } = new Resource(7); // N
public static Resource Oxygen { get; } = new Resource(8); // O
// and all the other elements....
}
}
InventoryItem.cs
public abstract class InventoryItem
{
public int ID { get; }
private static readonly Dictionary<int, InventoryItem> idList = new Dictionary<int, InventoryItem>();
public InventoryItem(int id)
{
ID = id;
idList[id] = this;
}
public static InventoryItem GetFromID(int id)
{
return idList[id];
}
}
When I use InventoryItem.GetFromID(int id) before accessing anything from the Resource class the dictionary is empty and nothing can be found. If I access any resource before they are in the Dictionary.
As the static fields in a class are only initialized when you first use that class, you have to somehow force this initialization, e.g. by calling any static method in Resource.
Example:
in Resource, add
public static void Initialize()
{
// can be left empty; just forces the static fields to be initialized
}
and somewhere else in your project
Resource.Initialize();
Alternatively you could initialize them in a static constructor.
It's like a default constructor except it is static.
It is similar to Java's static { ... } block
public class Resource : InventoryItem
{
public const int IDBase = 1000000;
public static Resource Hydrogen { get; }
public static Resource Helium { get; }
public static Resource Lithium { get; }
// ...
private Resource(int id) : base(IDBase + id)
{
}
private static Resource()
{
Hydrogen = new Resource(1);
Helium = new Resource(2);
Lithium = new Resource(3);
// etc...
}
}
Caveat - I haven't actually tried this but I think it's likely to work.
Static fields and properties are initialized in a type constructor, regardless of how you write it, so both:
static Resource()
{
Hydrogen = new Resource(1);
}
and
Hydrogen { get; } = new Resource(1);
Are the same thing, the only difference is the initialization order, also it would allow you to call static fuctions, but in OP's case it really doesn't make a difference, that's why pamcevoy's answer won't work.
Klaus provides a valid way of doing things, and it will work, just you would need to call the Initialize method before your GetFromID, at least once, as to initialize all of the Resource class's static properties, e.g.:
Resource.Initialize();
InventoryItem.GetFromID(id);
Your last option is to do method shadowing, basically add to your Resource class the same GetFromID method with the new operator and then call GetFromID through the Resource class, e.g.
public class Resource : InventoryItem
{
public static new InventoryItem GetFromID(int id)
{
return InventoryItem.GetFromID(id);
}
}
But know that method shadowing isn't the same as overriding a method, so if you call InventoryItem.GetFromID you won't be calling Resource.GetFromID. This will eliminate the need for calling at startup a separate Initialize method in the Resource class but, it will force you to, at least once, call GetFromID through the Resource class.
Update: At the end of the day, the only way to initialize static fields/props is by accessing one thing or another in said class.
I would have to create a constructor with great amount of parameters like:
new MyClass(param1, param2, param3, ..., param100);
Is there any way to initialize object like that in a gradual manner, like:
MyClass obj = new MyClass();
obj.Prop1 = val1;
obj.Prop2 = val2;
obj.checkIfInit() //I am not sure how to do that.
How to verify that it is initialized properly if the crazy constructor is not used?
It seems there is a high amount of repetition in your constructor, which is almost always an indicator of bad design. If possible, why not use a collection type, like an array:
new MyClass(paramArray);
Nice and clean.
If you really need that much parameters, you can usually group them together in categories. Make classes for each of them and pass those instances in. It will make use later on much easier too.
As others have pointed out, you should really not have a constructor with so many parameters - although with Dependency Injection for a data model type class, you do often end up with a lot of parameters. In that case, it's usually best to group the parameters into subsets encapsulated into their own classes.
Notwithstanding that advice, you can address the issue with a variant of the "Builder Pattern".
For example, given:
public sealed class MyClass
{
public MyClass(int prop1, string prop2, DateTime prop3)
{
Prop1 = prop1;
Prop2 = prop2;
Prop3 = prop3;
}
public int Prop1 { get; }
public string Prop2 { get; }
public DateTime Prop3 { get; }
}
First note that it has no default constructor and the properties are all read-only, making this class immutable (often a good idea).
(I have omitted parameter checking for brevity.)
Now you can write a helper class to build the object:
public sealed class MyClassBuilder
{
public MyClass Build()
{
if (!_prop1Set || !_prop2Set || !_prop3Set)
throw new InvalidOperationException("Not all properties set.");
return new MyClass(_prop1, _prop2, _prop3);
}
public MyClassBuilder Prop1(int value)
{
_prop1 = value;
_prop1Set = true;
return this;
}
public MyClassBuilder Prop2(string value)
{
_prop2 = value;
_prop2Set = true;
return this;
}
public MyClassBuilder Prop3(DateTime value)
{
_prop3 = value;
_prop3Set = true;
return this;
}
int _prop1;
string _prop2;
DateTime _prop3;
bool _prop1Set;
bool _prop2Set;
bool _prop3Set;
}
Each method for setting a property returns this, to enable fluent use like so:
var builder = new MyClassBuilder();
builder
.Prop1(1)
.Prop2("test")
.Prop3(DateTime.Now);
var myClass = builder.Build(); // Throws if not all properties set.
This gives you a great deal of flexibility for parameter validation and allowing some parameters to be omitted (by providing suitable defaults).
A real-world example of a builder class is Autofac's ContainerBuilder class, usage of which is described here.
Make all paramter to a class or struct , to help you make controctor be clean.
public class InitData
{
Parmter ....
}
new MyClass(InitData data);
Or use paramters
public class MyClass
{
public MyClass(params[] paramters)
{
foreach(p in paramters)
{ ... }
}
}
Possbie do not make a 'crazy controcter' is best soultion I think.
You can override Equals in order to check the default value:
public class MyClass {
public static readonly MyClass DefaultInstance = new MyClass();
public int Val1 { get; set; }
public int Val2 { get; set; }
// Etc...
public MyClass() {
this.Val1 = 10;
}
public override int GetHashCode()
{
unchecked // Overflow is fine, just wrap
{
int hash = 17;
// Suitable nullity checks etc, of course :)
hash = hash * 23 + Val1.GetHashCode();
hash = hash * 23 + Val2.GetHashCode();
return hash;
}
}
public override bool Equals(Object obj) {
if (obj == this)
{
return true;
}
var other = obj as MyClass;
return other?.Val1 == this.Val1 &&
other?.Val2 == this.Val2;
// Etc...
}
}
Then you can just check using:
if (MyClass.DefaultInstance.Equals(instanceToCheck)) {
... // All defaults
}
C# compiler implicitly gives you a default constructor if you are not writing any Constructor for a class.
Now, If you are explicitly giving an Constructor now the C# Compiler will not provide you any Constructor.
i.e you have only One Constructor with you =>MyClass(param1, param2, param3, ..., param100);
Now, You are trying to Create the object without any Parameters.=>MyClass obj = new MyClass();
So, there will be error every time you compile as the Compiler does not find this type of empty overload of the Constructor which one is not taking any value.
To avoid this use an empty constructor explicitly.
Look for the Following example.
Class1 cs = new Class1();
cs.x = "xyz";
cs.y = "zyx";
if(cs!=null)
{
//This checks the Object is created or not i.e Reference is created.
Console.Write("I'm intialized");
}
else
{
Console.WriteLine("I'm not initialized");
}
And the Class for Class1 follows
class Class1
{
public string x;
public string y;
public Class1(string x,string y)
{
this.x = x;
this.y = y;
}
public Class1()
{
}
}
Check it.
I need to create a method of class that delete the instance.
public class Car
{
private string m_Color;
public string Color
{
get { return m_Color; }
set { m_Color = value; }
}
public Car()
{
}
public void Delete()
{
/*This method will delete the instance,
so any references to this instance will be now null*/
}
}
class Program
{
static void Main( string[] args )
{
Car car = new Car();
car.Delete();
if(car==null)
Console.WriteLine("It works.");
else
Console.WriteLine("It doesn't work.")
}
}
I want to know if there is any possible solution (even if it is not recommended) how to do this.
Instance of this class will be stored in hundreds of different class. I will try to describe this, for example there will be these classes:
public class CarKey
{
private Car m_Car;
public Car Car
{
get { return m_Car; }
}
public bool CarExist{ get{ return m_Car != null; } }
public CarKey( Car car )
{
m_Car = car;
}
}
public class Garages
{
private List<Car> m_Collection = new List<Car>();
private int m_Size;
public int Size{ get{ return m_Size; } }
public Garages( int size )
{
for(int i=0;i<size;i++)
m_Collection.Add(null);
}
public bool IsEmpty( int garage )
{
return m_Collection[garage] == null;
}
public void InsertCar( Car car, int garage )
{
if( m_Collection[garage] != null )
throw new Exception("This garage is full.");
m_Collection[garage] = car;
}
public Car GetCar( int garage )
{
if( m_Collection[garage] == null )
throw new Exception("There is no car, maybe it was deleted.");
return m_Collection[garage];
}
}
From any class you can't set its value to null. This is not allowed and doesn't make sense also -
public void Delete()
{
this = null; <-- NOT ALLOWED
}
You need an instance of class to call Delete() method so why not set that instance to null itself once you are done with it.
Car car = new Car();
// Use car objects and once done set back to null
car = null;
Anyhow what you are trying to achieve is not possible in C#. I suspect
from your question that you want this because there are memory leaks
present in your current design which doesn't let the Car instance to
go away. I would suggest you better profile your application and
identify the areas which is stopping GC to collect car instance and
work on improving that area.
I would suggest , to use .Net's IDisposable interface if your are thinking of to release instance after its usage.
See a sample implementation below.
public class Car : IDisposable
{
public void Dispose()
{
Dispose(true);
// any other managed resource cleanups you can do here
Gc.SuppressFinalize(this);
}
~Car() // finalizer
{
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
if (_stream != null) _stream.Dispose(); // say you have to dispose a stream
}
_stream = null;
_disposed = true;
}
}
}
Now in your code:
void main()
{
using(var car = new Car())
{
// do something with car
} // here dispose will automtically get called.
}
It sounds like you need to create a wrapper around an instance you can invalidate:
public class Ref<T> where T : class
{
private T instance;
public Ref(T instance)
{
this.instance = instance;
}
public static implicit operator Ref<T>(T inner)
{
return new Ref<T>(inner);
}
public void Delete()
{
this.instance = null;
}
public T Instance
{
get { return this.instance; }
}
}
and you can use it like:
Ref<Car> carRef = new Car();
carRef.Delete();
var car = carRef.Instance; //car is null
Be aware however that if any code saves the inner value in a variable, this will not be invalidated by calling Delete.
What you're asking is not possible. There is no mechanism in .Net that would set all references to some object to null.
And I think that the fact that you're trying to do this indicates some sort of design problem. You should probably think about the underlying problem and solve it in another way (the other answers here suggest some options).
You can proxyfy references to your object with, for example, dictionary singleton. You may store not object, but its ID or hash and access it trought the dictionary. Then when you need to remove the object you set value for its key to null.
You cannot delete an managed object in C# . That's why is called MANAGED language. So you don't have to troble yourself with delete (just like in c++).
It is true that you can set it's instance to null. But that is not going to help you that much because you have no control of your GC (Garbage collector) to delete some objects apart from Collect. And this is not what you want because this will delete all your collection from a generation.
So how is it done then ? So : GC searches periodically objects that are not used anymore and it deletes the object with an internal mechanism that should not concern you.
When you set an instance to null you just notify that your object has no referene anymore ant that could help CG to collect it faster !!!
Use a collection that is a static property of your Car class.
Every time you create a new instance of a Car, store the reference in this collection.
To destroy all Cars, just set all items to null.
FLCL's idea is very correct, I show you in a code:
public class O1<T> where T: class
{
public Guid Id { get; }
public O1(Guid id)
{
Id = id;
}
public bool IsNull => !GlobalHolder.Holder.ContainsKey(Id);
public T Val => GlobalHolder.Holder.ContainsKey(Id) ? (T)GlobalHolder.Holder[Id] : null;
}
public class GlobalHolder
{
public static readonly Dictionary<Guid, object> Holder = new Dictionary<Guid, object>();
public static O1<T> Instantiate<T>() where T: class, new()
{
var a = new T();
var nguid = Guid.NewGuid();
var b = new O1<T>(nguid);
Holder[nguid] = a;
return b;
}
public static void Destroy<T>(O1<T> obj) where T: class
{
Holder.Remove(obj.Id);
}
}
public class Animal
{
}
public class AnimalTest
{
public static void Test()
{
var tom = GlobalHolder.Instantiate<Animal>();
var duplicateTomReference = tom;
GlobalHolder.Destroy(tom);
Console.WriteLine($"{duplicateTomReference.IsNull}");
// prints true
}
}
Note: In this code sample, my naming convention comes from Unity.
You can use extension methods to achive this.
public static ObjRemoverExtension {
public static void DeleteObj<T>(this T obj) where T: new()
{
obj = null;
}
}
And then you just import it in a desired source file and use on any object. GC will collect it. Like this:Car.DeleteObj()
EDIT
Sorry didn't notice the method of class/all references part, but i'll leave it anyway.
I'm working on an object in C# where I need each instance of the object to have a unique id. My solution to this was simply to place a member variable I call idCount in the class and within the constructor I would have:
objectID = idCount;
idCount++;
I thought that this would solve my problem but it seems that idCount never gets incremented even though the constructor gets called multiple times. For example if idCount = 1, the objectID for all the objects are still 1. Why doesn't idCount++ work?
Any help would be appreciated. Apologies if my explanation isn't adequate, I'm not sure how else to explain it.
You need a static property in your class, BUT, you need to assign it to an instance variable within the class if you want each object to contain the id it was created with.
Also, you'll want to use Interlocked.Increment on the counter in case you are updating multiple instances simultaneously:
public class Foo
{
private static int m_Counter = 0;
public int Id { get; set; }
public Foo()
{
this.Id = System.Threading.Interlocked.Increment(ref m_Counter);
}
}
You could use a static variable in your class that gets updated when the object is initialized.
public class Foo
{
private static int ID = 0;
private int myId = 0;
public int MyId
{
get { return myId; }
}
public Foo()
{
ID++;
this.myId = ID;
}
}
As everyone has pointed out, static variables are the specific answer to your question. But static variables only have scope within the process in which they were created and there is no relationship across processes (for example, a load balanced web environment).
If what you are looking for is a unique way to identify an object instance for the duration of its lifetime, I suggest something like:
byte[] bytes = new byte[8];
RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider();
crypto .GetBytes( bytes );
long id = BitConverter.ToInt64( bytes, 0 );
This will give you a random number which has an extremely low (roughly 0-1 in 100,000,000) chance of collision and you don't need to worry about keeping track of it.
You set IdCount is static member of MyObject.
public class MyObject
{
static int idCount = 0;
private int _objectID;
public int ObjectID
{
get { return _objectID; }
}
public MyObject()
{
idCount++;
_objectID = idCount;
}
}
public sealed class SingletonIdGenerator
{
private static long _id;
private SingletonIdGenerator()
{
}
public string Id
{
get { return _id++.ToString().Substring(8); }
}
public static SingletonIdGenerator Instance { get { return Nested.instance; } }
private class Nested
{
static Nested()
{
_id = DateTime.Now.Ticks;
}
internal static readonly SingletonIdGenerator instance = new SingletonIdGenerator();
}
}