I created an object, and I assigned it to two variables found in separate classes.
If in one class I set the variable to null, it only breaks that reference to the object but the object itself still persists due to the other reference.
How do I set the object to null, so that both references point to null? Without finding every reference.
this is pseudocode. The idea is to lose the reference in both ClassA (ref1) and ClassB (ref2).
public class ClassA
{
public ClassC ref1 = new ClassC ();
static void Main(string[] args)
{
ref1 = null;
}
}
public class ClassB
{
public static ClassC ref2;
public static AssignC (ClassC c)
{
ref2 = c;
}
}
public class ClassC
{
public ClassC ()
{
ClassB.AssignC (this);
}
}
You can't.
You cannot reach into the internals of another class, (well, not conventionally.) This form of Encapsulation makes .Net code much easier to debug.
You could write a function on the class that sets all its members to null, you could do this as an implementation of IDisposable.
When there are no references to an object the Garbage Collector will reclaim the memory, you cannot directly control this.
You could rewrite your example like this.
public class A
{
private C c = new C();
static void Main(string[] args)
{
c.Dispose();
c = null;
}
}
public static class B
{
private static C c;
public static LastC
{
get
{
return c;
}
set
{
c = value;
}
}
}
public class C : IDisposable
{
public C()
{
B.C = this;
}
public void Dispose()
{
if (B.LastC == this)
{
// LastC has not been set by another instance.
B.LastC = null;
}
}
}
You'll note that I've made the static reference accessible via a setter, so that other classes can access it.
Setting null to reference-type variable change only VALUE of that particular variable - reference to object. Good article by Jon Skeet - http://www.yoda.arachsys.com/csharp/parameters.html
In your case its better to wrap object into Singleton pattern. So the setting of null to main variable will destroy the only reference to object and it can be garbage-collected.
It is simply not possible.
References can be either null or point to an actual instance. When you assign, as in ref2 = c; the value of one reference is copied to another reference. After that you have two references to the same instance. (The instance is not copied, for sure, only the reference; these are reference types.)
When you do ref1 = null; that just overwrites the particular reference with one that points to "nothing". It doesn't destroy any instance, just makes a single reference "point" to something else. Other references are unaffected (method parameters with ref or out of currently executing methods could in fact be the same reference, the one which is turned to points elsewhere).
In the question title you say "set the instance to null", but that doesn't really make sense, because an instance is an object (not a reference).
So how to destroy an instance? You can't. The garbage collector might come by at some point (when you are about to allocate a new object) and see that some instances have zero references to them. It will then remove the instances from memory.
You can't "zero" other people's references. Just because you have one references to an instance, there is no way to say "search through the entire application and find other references that happen to point to the same instance right now, and change all those references. That would be a really terrible thing to allow, because people could never be sure when their variables changed out of nowhere.
Related
Is it possible to get the declaration name of a class (dynamically) and pass it as a parameter in the constructor to set the name variable in the class itself?
Example:
public class Foo
{
public string name;
public Foo()
{
name = GetClassName();
}
}
public class SomeOtherClass
{
Foo className = new Foo();
Console.WriteLine(foo.name);
}
As result I would expect it to write: "className".
No. That is not possible. There is no way to pass in a variable name without using a parameter.
This is the closest you can get:
Foo className = new Foo(nameof(className));
That sounds like a weird requirement. A variable is nothing but a reference to an object. The name of that reference has by no means anything to do with what this variable reference. Thus the actual referenced object doesn´t know anything about its references. In fact you may have even multiple references to the same Foo-instance. So how should the instance know to which variable you refer to? So what should happen in the following example:
var f = new Foo();
var b = f;
Now you have two references to the same instance of Foo. The instance can´t know which of hose is the right, unless you provide that information to it by using a parameter (e.g. to your constructor). The thing gets even worse if you have a factory creating your Foo-instance:
void CreateFoo()
{
return new Foo();
}
// ...
var f = CreateFoo();
Now you have a further indirection, the constructor of Foo can surely not bubble though all layers in your call-stack until it reaches some assignement where it may get the actual name. In fact it´s possible that you don´t even assign your instance to anything - although this is merely a good idea:
CreateFoo(); // create an instance and throw it away
Anyway if you want to set a member of an instance to some value, you should provide that value to the instance. The answer by Patrick shows you how to do so.
Out of curiosity: Is there a way to create a class whose reference to the class instance can never be set to null?
Like haveing only a readonly pointer that can only be set to null by the class itself.
What I have in mind:
I would want to have an easy to read /use object that either exists with data or exists without (shown by an attribute like hasData = false). It is always accessable and should never be null / point to nowhere which as a side effect gets also rid of NullReferenceExceptions for objects that are sometimes supposed to not have a value without the need of checking for null.
This feature does not exists (yet). There is big discussion of non-nullable reference types at Roslyn forum: non-nullable reference types (the one billion $ mistake). But currently you cannot restrict reference type variable from assigning null value.
You can use value type (struct) instead, but it's not stored in heap, passed by value etc.
All other options will not guarantee that someone will not assign null to variable of your reference type. But you still can use something like Null Object pattern to simplify your life (processing objects without data in same way as usual objects).
In such a case, you may want to use a struct instead of a class. Class is a reference type and therefore its default value is null, hence a variable containing an instance can be nulled (assigned null). There is no way to prevent it. On the other hand, struct is a value type and default for struct is an empty struct - i.e. a struct whose members are set to their defaults (0 for an int field, null for a field of a reference type etc.)
Example of a struct
public struct Foo
{
public int Bar;
}
And its usage (notice it is not instantiated but still it is NOT null)
Foo foo;
foo.Bar = 1;
More about structs can be found here on the MSDN sites.
As Anton mentioned, you could use a struct which cannot have a default value of null. But I am thinking you want something more like this:
public class DataObject
{
public static bool HasData
{
get
{
return myObject != null;
}
}
public static DataObject PresistentDataObject
{
get
{
return myObject;
}
}
static DataObject myObject = new DataObject();
}
This code seems like bad practice. And maybe you'd want to resort to something like dependency injection with a singleton which will avoid setting up a state class like this.
Typically, the motivation behind such a question drives the qualities/properties of a solution.
Here, I suppose, the motivation is to avoid runtime exceptions of (faulty) code which tries to access a null reference as if it held an instance.
class Foo<T> {
T data; // might be null or hold an instance...
Foo<T>() {
data = GetInstanceOfTInMysteriousWays(); // might return null...
}
bool DoSomething() {
return data.Value > 5; // might throw an exception...
}
// ... more members...
}
To prevent this type of errors, you could borrow from C#'s cousin language F#.
If the function T GetInstanceOfTInMysteriousWays<T>() by design and contract is permitted to either return an instance or a null value, a better design of that function would be to have it return not T but an Option<T>. Then, the type of Foo.data would not be T but Option<T> and the user code in DoSomething() could not simply access member data.Value. Thus, this common pattern of bugs would be eliminated.
// Improved code from above
class Foo<T> {
Option<T> data; // Option is a struct type and cannot be null...
Foo<T>() {
data = GetInstanceOfTInMysteriousWays();
}
bool DoSomething() {
if (data.IsSome() ) {
return data.TryGetValue().Value > 5;
}
return false;
}
}
Now the only question is, where to find that Option type in C#? There are several github projects creating such a type (google is your friend). You could also consider to link the F# core library and use the Option type defined there, maybe along with a little helper as is shown in this gist snippet.
If your class is named foo, then you would have at least one constructor (possibly more). In that constructor you would assign the variable to false.
public foo(){
hasData = false;
}
As #Anton points out, this only works if the variable is instansiated.
foo f = new foo();
it would still be null if you assigned it as null:
foo f = null;
I'm not sure, I understand the question correctly or not. Let me add
some points here:
Hope that you misunderstand the term Instance, If you create an instance of the class then it will not be null, Let myClass be a class that you have created already. You are not creating any instance of the class by using myClass myClassObject. The myClassObject will became an instance of the class only when an instance of the class is assigned to it, Until then it is null which means not existing.
As others have mentioned, you'd need a struct for that.
However, we can tackle this from a different angle (in a class):
Since the variable can point to null, let's define the variable in a way that it can't be set to null:
private Class1 _c = new Class1();
public Class1 c { get { return _c; } set { if (value != null) _c = value; } }
so c will not be set to null.
A struct per your requirements:
struct Struct1
{
public bool hasData { get { return Data != null; } }
public Class1 Data;
}
The application is printing 24 but shouldn't it be printing 18 when we know that without ref keyword only a copy of object is passed and no change is made to the original object.
I have created a class called myclass and an object me. age is a public variable in class myclass.
I have set me.age as 18 and through the method show I have changed it to 24.
class Program
{
static void Main(string[] args)
{
myclass me = new myclass();
me.age = 18;
show(me);
Console.WriteLine(me.age);
Console.ReadLine();
}
public static void show( myclass you)
{
you.age = 24;
}
}
class myclass
{
public int age;
}
Don't confuse the variable and what the variable points to.
When you have:
MyClass myVar = new MyClass();
MyClass myVar2 = myVar;
That will create only a single instance of an object, but 2 variables pointing to it.
The same thing is happening to your parameter: you is a copy of the variable me, but both point to the same object. So when you modify you.age, you are also modifying me.age.
In your function, if you then did
you = new myClass();
only then would me and you refer to different objects. If you did this, me would still point to the original object.
If you added ref to the parameter you, then if you did
you = new myClass();
then the variable me would be updated to point to that same object.
For objects, you need to separate the variable from what the variable points to.
It's printing the right thing.
myclass is an object, and the default behavior is to pass the reference of the object in C#, so when you don't specify anything, you pass the reference.
If you declare struct myclass though, you'll have the behavior you want, because structs aren't references by default.
You're probably confusing this with C++ classes. In C#, classes are reference types, which means that whenever you have a variable of a type that's class, that variable doesn't hold the object itself, it holds only a reference to it (you can think of it as a pointer). So, when you pass your object into a method, you actually pass a reference to that object. This means the behavior you're observing is correct.
C# also supports value types (unlike e.g. Java), which you create by using struct instead of class. If you changed myclass into a srtuct, you would get the behavior you expected.
You are confusing value types and reference types.
public void addTwo(int a)
{
a += 2;
}
...
int a = 5;
addTwo(a);
Console.WriteLine(a); // will give "5";
public void addTwo(ref int a)
{
a += 2;
}
...
int a = 5;
addTwo(ref a);
Console.WriteLine(a); // will give "7";
For reference types (anything that is defined as class instead of struct, what you are passing on is a reference to the object, not a copy. So you are in fact changing the object.
You are sending an object to your function.
Not an atomic type or a struct, therefor it is sent by reference (this is how C# works), anything you change in this object in the function will also change in the original object because it is the same.
More information about passing parameters: http://msdn.microsoft.com/en-us/library/0f66670z(v=vs.71).aspx
In this question I would like to find out if and how this is possible. This technique would seem extremely bad practice but it seems that the API (UnityEditor) that I am using, is doing something like this and I am just curious.
If there are multiple references to the same object, is it possible to instantiate a new object into the same memory slot so that all previous references point to the new object?
I figured out that the only feasible way to do so is by using unmanaged C++. Essentially the following is happening:
// Original prefab
GameObject prefab = x;
prefab.tag = "Untagged";
// A copy of the original prefab
GameObject prefabCopy = PrefabUtility.InstantiatePrefab(prefab) as GameObject;
prefabCopy.tag = "EditorOnly"; // Change from initial value "Untagged"
Debug.Log(prefab.tag); // "Untagged" - expected
Debug.Log(prefabCopy.tag); // "EditorOnly" - expected
// Replace contents of prefab file with `prefabCopy`
PrefabUtility.ReplacePrefab(prefabCopy, prefab);
// Destroy the copy
DestroyImmediate(prefabCopy);
Debug.Log(prefab.tag); // "EditorOnly" - whoa?
Some how prefab is now pointing to a different object?
Note: Bear in mind that Unity is built on top of the Mono flavour of .NET
Since an object state is defined by field values, you can copy memory, containing field values, from one object to another, effectively "replacing" it:
public static void Replace<T>(T x, T y)
where T : class
{
// replaces 'x' with 'y'
if(x == null) throw new ArgumentNullException("x");
if(y == null) throw new ArgumentNullException("y");
var size = Marshal.SizeOf(typeof(T));
var ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(y, ptr, false);
Marshal.PtrToStructure(ptr, x);
Marshal.FreeHGlobal(ptr);
}
Note that this code requires [StructLayout(LayoutKind.Sequential)] (or LayoutKind.Explicit) attribute defined for a class.
You could do that if you embed your object into another one that is used to access the object.
class ObjectReference<T>
where T : new()
{
private T _obj = new T();
public void CreateNewObject()
{
_obj = new T();
}
public T Value { get return _obj; }
}
Now you can create multiple references to an object of type ObjectReference and only change the local object. The "real" object would be accessed through the Value property
A slightly different approach is that you create a wrapper that implements the same interface as your "real" object, thus making this wrapping transparent.
interface ISomeInterface
{
string PropertyA { get; set }
void MethodB (int x);
}
class TheRealObject : ISomeInterface
{
public string PropertyA { get; set }
public void MethodB (int x)
{
Console.WriteLine(x);
}
}
class Wrapper : ISomeInterface
{
TheRealObject _obj = new TheRealObject();
public string PropertyA
{
get { return _obj.PropertyA; }
set { _obj.PropertyA = value; }
}
public void MethodB (int x)
{
_obj.MethodB(x);
}
public void CreateNewObject()
{
_obj = new TheRealObject();
}
}
Now the wrapper can be used as if it was the "real" object. You could also pass an initial instance of the "real" object in the wrapper's constructor and remove the initializer of _obj.
No, that's not possible.
To actually change all references to an object, you would have to freeze all threads in the process, and access their register sets and stack. That's what the garbage collector does, but it's not possible for regular code.
What the method most likely does is to make a deep copy of one object onto the other.
If it is a custom Class you want to reference, i think you can have all the references point to a Fake Reference...
create your class (A)
create your class Interface (IA)
Create a wrapper class based on your interface which just passes all calls to a contained object (AC)
I Added a Assignment operator so i have all A Objects as ACs.
class AC:IA
{
IA ref;
AC(IA ref)
{
this.ref = ref;
}
public void ChangeReference(IA newRef) { ref = newRef;}
public static operator = (IA assignedObj)
{
return (assignedObject is AC) ? assignedObject : new AC(assignedObj);
}
// implementation of all methods in A
public override string ToString() { return ref.ToString(); }
...
}
Now if you want, you can use the ChangeReference method to switch all to the new Reference..
in C++ you would use Reference to Reference
Best of luck
I am having a dispute with another fellow programmer, over the scope of interfaces.
suppose we have the following:
public interface IFoo
{
string Bar { get; set; }
}
public class SomeFoo: IFoo
{
public string Bar { get; set; }
public SomeFoo(string bar)
{
this.Bar = bar;
}
}
public class Consumer
{
public void DoSomething()
{
SomeFoo fooClassInstance = new SomeFoo("test");
IFoo fooInterface = (IFoo)fooClassInstance;
// do something with fooInterface.
}
}
So the question is:
1. Is it possible the fooClassInstance to go out of scope before something else releases the fooInterface instance?
Some argue that the object (fooClassInstance) can go out of scope.
I believe that it cant. Sure, objects may or may not get disposed of by the GC when the GC decides that the object(s) are no longer in scope. However since Interfaces are by design an abstract contract whose members have to be implemented by the object that uses it, than an interface cannot lose its implementation so long as the interface is used. It's not like a whole another object is created of type "interface". The interface is merely a pointer to those abstract members of the implementor.
Can you guys help me resolve this dispute?
Thanks,
<bleepzter />
While there is definitely some confusion in the terms you are using (I'll let someone else tackle that issue), I think I understand what you are saying, and you are basically right.
In particular, it sounds like your coworker believes this is happening:
// Now there is this "SomeFoo" object somewhere in memory.
SomeFoo fooClassInstance = new SomeFoo("test");
// Now there is this "IFoo" object somewhere in memory.
IFoo fooInterface = (IFoo)fooClassInstance;
// Let's say down the road somewhere, fooClassInstance is set to null or a different
// object. Your coworker believes that the object it originally pointed to will then
// have no references to it and will thus be eligible for garbage collection?
If the above is an accurate representation of what your coworker thinks, then your coworker is wrong and you are right. The fooInterface variable contains a reference to the same object that fooClassInstance had a reference to. You can easily verify this simply by doing the following:
SomeFoo fooClassInstance = new SomeFoo("test");
IFoo fooInterface = (IFoo)fooClassInstance;
bool sameObject = ReferenceEquals(fooClassInstance, fooInterface);
If ReferenceEquals returns true, then the two variables are referencing the same object in memory.
If your coworker needs further convincing, try showing him/her something like this:
List<int> list = new List<int> { 1, 2, 3 };
// This cast is actually not needed; I'm just including it so that it mirrors
// your example code.
IList<int> ilist = (IList<int>)list;
// Now we remove an item from the List<int> object referenced by list.
list.Remove(3);
// Is it in ilist? No--they are the same List<int> object.
Console.WriteLine(ilist.Contains(3));
// How about we remove an item using ilist, now?
ilist.Remove(2);
// Is it in list? Nope--same object.
Console.WriteLine(list.Contains(2));
// And here's one last thing to note: the type of a VARIABLE is not the same
// as the type of the OBJECT it references. ilist may be typed as IList<int>,
// but it points to an object that is truly a List<int>.
Console.WriteLine(ilist.GetType());
I think you are muddling the line between instance an reference. fooClassInstance can go out of scope (that is, it can no longer be referenced) even if the instance of the object still exists (because fooInterface still holds a reference to it).
For example, if you do the following, fooClassInstance will not be available after the braces, but fooInterface will.
public void DoSomething()
{
IFoo fooInterface;
{
SomeFoo fooClassInstance = new SomeFoo("test");
fooInterface = (IFoo)fooClassInstance;
}
// do something with fooInterface, but NOT with fooClassInstance
}
Uh, what do you mean by "lose its implementation"? That makes no sense. A type implements an interface, it cannot "unimplement" an interface.
As far as your code example goes, the lifetime of the object allocated ends the instant it no longer has any roots (aka, is no longer reachable by the GC). A reference to it is a reference to it, regardless of the type of the reference (i.e. if the reference type is of some derived or parent type, it doesn't matter).
ISomething Sample() {
Something s1 = new Something();
s2.DoSomething(); // Assuming s is the only reference to s, then it no longer is
// rooted after this expression
Something s2 = new Something();
ISomething is1 = s2;
s2 = null;
is1.DoSomething(); // The reference remains valid and the lifetime of the
// object created continues until we release all
// remaining references to it.
return is1;
}
It sounds like you are correct, but I feel like we're missing part of the discussion since we don't know what you're doing with the object after you create (and cast) it.
In your example:
SomeFoo fooClassInstance = new SomeFoo("test");
At this point, you have one reference to the SomeFoo object referenced by fooClassInstance.
IFoo fooInterface = (IFoo)fooClassInstance;
At this point, you have two references to the SomeFoo object (referenced by both fooClassInstance and fooInterface).
So yes, depending on how you use it, fooClassInstance could go out of scope. But there is still a reference to it (fooInterface) so it wouldn't be garbage collected. Also, the fooInterface reference could be cast back to SomeFoo.