Lets assume I instantiated MyClass. Does my Foo property have a reference at this point or is it null? Also what happens after I call UseFoo() and exit the scope? Did I dispose Foo or just foo?
public class MyClass
{
private readonly string param;
private IDisposable Foo => new Foo(param);
public MyClass(string param)
{
this.param = param;
}
public void UseFoo()
{
using var foo = Foo;
// use foo
}
}
Q: Does my Foo property have a reference at this point or is it null?
A: No, because the property does not have a backing field, aka state.
Instead, every time you read the value of Foo, you will construct a new instance of the Foo type and return that.
As #juharr so nicely put it in their comment, it is a property but behaves like a method.
Q: Also what happens after I call UseFoo() and exit the scope? Did I dispose Foo or just foo?
A: You disposed the single object that you got from reading the Foo property and stored in the foo local variable.
Since the Foo property does not actually have state, you only disposed the object that was constructed for you when you read the Foo property.
The next time you read the Foo property you will get a new instance.
I find it helpful to mentally translate => to "returns". It is an active operation, not a passive assignment. So in your case, I would read it as "Foo returns a new foo of param".
When it comes to properties,
private IDisposable Foo => new foo(param);
is equivalent to
private IDisposable Foo
{
get { return new foo(param); }
}
Related
Given the following code, should I only dispose foo when it was created by within the Bar class? Or should I always dispose foo even when it was passed to a constructor? I'm thinking I should probably add another private variable to keep track of whether Bar created foo or whether it was passed to the Bar( Foo foo ) constructor, and only dispose of foo when it was created by the public Bar( string name ) constructor.
public class Bar: IDisposable
{
private Foo foo = null;
public Bar( string name )
{
this.foo = new Foo(name);
}
public Bar( Foo foo )
{
this.foo = foo;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose( bool disposing )
{
if( disposed )
return;
if( disposing )
foo.Dispose();
this.disposed = true;
}
}
You're correct in your thinking.
If you're passed an instance of Foo from elsewhere, and dispose of it yourself, you might break code still consuming the Foo. If you create an instance of Foo but don't dispose of it, you'll hang on to the memory it consumes unnecessarily long.
So, your best option is to track whether you created the instance yourself and dispose of it if so. (You could also allow the caller to specify the behaviour, as has been mentioned in the comments.)
(Alternatively, you could not do anything, which will be more inefficient but will at least not break anything. The only solution that is likely to actively break something is if you dispose of the instance that's been passed in from elsewhere.)
I have a class where I declare an object, but don't initialize the object. Then I pass the object to a method in another class for initialization. What I expect to happen is that the object in the calling class will now have a reference to the initialized object, but instead it is null.
Here is an example of what I mean:
class MainClass
{
ObjectA foo;
OtherClass.InitializeObjectA(foo);
// why is foo null over here?
}
class OtherClass
{
public static void InitializeObjectA(ObjectA device)
{
device = new ObjectA();
}
}
My problem is that device when I try to use foo after calling InitializeObjectA() it is still pointing to null! If I change InitializeObjectA() to out ObjectA device it works. Can anyone explain why this is needed?
If you want this to work, you need to pass by reference:
public static void InitializeObjectA(ref ObjectA device)
{
Or:
public static void InitializeObjectA(out ObjectA device)
{
Without that, InitializeObjectA sets the device parameter to a new ObjectA(), but that will not affect the caller, because, by default, references are passed by value.
Note that, if you're just trying to initialize, returning an instance instead of void is often a better way to handle this:
public static ObjectA InitializeObjectA()
{
return new ObjectA();
}
This avoids the need to use ref or out passing.
A class is a reference type, you pass the address of foo as parameter (copy), within you change the copy, but the new address won't be set back to the original foo. This will only be done with the out or ref keyword.
The simplest way to create the instance of ObjectA named foo is to return the instance to assign to the variable
class MainClass
{
ObjectA foo = OtherClass.InitializeObjectA();
}
class OtherClass
{
public static ObjectA InitializeObjectA()
{
return new ObjectA();
}
}
Why not just have the Initialize method return the created object?
class MainClass
{
var foo = OtherClass.InitializeObjectA(foo);
}
class OtherClass
{
public static ObjectA InitializeObjectA(ObjectA device)
{
return new ObjectA();
}
}
From what I understand, the C# compiler doesn't actually initialize variables for you like that. I'm not even able to compile this code in Visual Studio 2010, because it's an error to pass an uninitialized parameter to a function.
You want:
ObjectA foo = null;
Which is I think what you're trying to do anyway, C# just doesn't do it for you as it would in Java. This still doesn't get the behavior I think you're trying to achieve though, which is probably best accomplished by refactoring your code to something like
ObjectA foo = InitializeObjectA()
public static ObjectA InitializeObjectA(){
return new ObjectA();
}
Alternately, you can use pass by reference, where you pass a reference (or pointer if you're familiar with it) to the function, so changes made to that reference are reflected outside the scope of your function.
That's because when you do
device = new ObjectA();
you are setting the object to a new one, with a different reference in memory.
You should do something like:
class MainClass
{
ObjectA foo = OtherClass.InitializeObjectA(foo);
}
class OtherClass
{
public static ObjectA InitializeObjectA(ObjectA device)
{
return = new ObjectA();
}
}
or instead
class MainClass
{
ObjectA foo = null;
OtherClass.InitializeObjectA(out foo);
}
class OtherClass
{
public static void InitializeObjectA(out ObjectA device)
{
device = new ObjectA();
}
}
More information about why this happens can be found here.
Using C#.
I have a MainFoo class:
class MainFoo
{
private Foo foo;
public MainFoo()
{
this.foo = new Foo();
}
public CreateNewFoo()
{
this.foo = new Foo();
}
public DoCurrentFoo()
{
this.foo.Do();
}
}
A Foo class:
class Foo
{
~Foo()
{
this.DoEnd();
}
public void Do() {}
private void DoEnd() {}
}
I want to be able to call the method DoEnd() in Foo class whenever private Foo; get's initialized again. This method DoEnd() is private and I would like to keep it that way (so not accessible from MainFoo).
Since the same Foo get's initialized again, I though the instance would loose it's reference so it would call destructor. But this gets only called when MainFoo instance lost reference.
Question: How to dispose object instance when it lost it's reference?
Destructors are not guaranteed to be called at any specific time, or even get called at all. Typically, you should not rely on destructor and should implement IDisposable and call Dispose yourself.
Most conviniently, this can be done with using(...){ }.
Getting back to your sample, you can also dispose object on assignment of property (as Jason Watkins suggested), but make sure that it is not used anywhere else.
public Foo F
{
get{return foo;}
set
{
if( foo != null)
foo.Dispose();
foo = value;
}
}
You cannot, it's the Garbage Collector's job.
From MSDN:
In C#, garbage collection is handled by the common language runtime (CLR) with similar functionality to that of the JVM. The CLR garbage collector periodically checks the memory heap for any unreferenced objects, and releases the resources held by these objects.
I am trying to minimize entity framework connection context scope using "using" while at the mean time I want to be able to inject a context into my class.
I searched on internet but did not find a case like mine, or I am just doing something wrong, anyway, here is code:
[TestFixture]
public class Dummy
{
private IFoo ifoo;
[Test]
public void CreateIfNotExist()
{
using (var foo = GetNewIFoo())
{
foo.Dosomething();
}
Assert.IsNull(ifoo);//test fail here
}
[Test]
public void NotCreateIfExist()
{
ifoo = new Bar();
using (var foo = GetNewIFoo())
{
foo.Dosomething();
}
Assert.IsNull(ifoo);//test fail here
}
private IFoo GetNewIFoo()
{
if (ifoo == null)
{
ifoo = new Foo();//return new Foo();
}
return ifoo;
}
}
the first test failed, with a object sequence of foo created->foo do something->foo disposed(called by using on foo) while the state variable ifoo is still type of Foo().
Second test failed, with object life sequence as same as before.
I am confused as I thought GetNewIFoo() would return a reference of ifoo and using keyword would just call dispose on ifoo?
Also, is there any good way to control context scope while maintaining ability to inject IContext ?
Calling Dispose() does not clear the references (nor does it perform garbage collection). It simply calls the Dispose() method, which can (for example) close connections, files, etc - depending on the implementation. An object can be non-null and still disposed. Some objects allow you to see if an object is disposed; most don't.
Generally, if you are using something, you wouldn't write that variable somewhere else (i.e. you wouldn't write it as a field somewhere).
Meaning if using block is in next:
using (var foo = GetNewIFoo())
{
foo.Dosomething();
} // foo.Dipose() will be called automatically
which is the same as:
var foo = GetNewIFoo())
try
{
foo.Dosomething();
}
finally
{
foo.Dipose();
}
so foo is not null after using, but it's disposed.
Also:
using (var foo = GetNewIFoo())
{
foo.Dosomething();
}
//^ nothing below affects ifoo!!
Assert.IsNull(ifoo); // so why reference should be null??
Doesn't object initialization outside of a constructor break encapsulation ?
Given:
class MyClass
{
public string _aString;
}
Shouldn't the _aString member be private and instantiated via a call to the constructor (constructor omitted here):
MyClass test = new MyClass("test");
Instead of the alternate method of object initialization:
MyClass test = new MyClass { _aString = "Test" };
"Doesn't object initialization outside of a constructor break encapsulation ?"
Well, no. As you rightly pointed out you can only initialize properties that are already accessible in your current scope. (public, internal etc)
This kind of Intialization is really just some syntactic sugar around construction of a class and assigning values to properties, It is very useful for Anonymous classes and Linq select clauses.
It is usually considered bad practice to expose public fields... it may be acceptable in some cases, for instance if the field is marked as readonly (which means it must be set in the constructor). Instead, you should make this field private and expose it through a property, which may or may not be readonly, depending on its purpose :
class MyClass
{
private string _aString;
public string AString
{
get { return _aString; }
// uncomment to make the property writable
//set { _aString = value; }
}
}
If you consider Properties as getters and setters, I don't believe it will break encapsulation. But you should notice that you didn't use a Property, you have used an instance variable. In fact, I don't believe it will work like your example. Check this one:
class MyClass {
private string aString;
public string AString {
get { return aString; }
set {aString = value; }
}
}
MyClass test = new MyClass {
AString = "test"
};
In this case, you are accessing the private field through it's accessor. It's just like using a parameterless constructor and setting the value later.
It depends on the purpose of the variable. If the programmer should only be able to set the variable at initialization, but then not have access to it after that, then I would go with the private variable. If you want the class user to be able to set / read the variable at any time, then make it public.
When you have
public string _aString;
it really does not matter when you initialize this value since this is already exposed. So, when we want to talk about initialization we should move this string into property. Than talkin about encapsutlation makes sense.
So, imagine we have some string. There are mosly two approaches to initializatnion. One is to do it inside constructor, second is lazy initialization (initialize when some request this data).
yes, initialize via the constructor, and add properties to allow (or not) access to the data.
class MyClass {
private string _aString;
string MyProperty {
get { return this._aString; }
// you can make this private or protected
set { this._aString = value; }
}
}
If you're asking if the new object initialization shorthand breaks encapsulation, then the answer is no. You can only set publicly scoped members with the new method.
MyClass test = new MyClass { _aString = "Test" };
is the same as
MyClass test = new MyClass();
test._aString = "Test";
To show an object public in a C# class does not break "encapsulation" from a point of view of "Object-oriented programming".
From a point of view of a "good practise" it not a good thing, use Properties because it allows to external code to use this class if you change the behaviour of updating this value (checking, ...).