Instantiated variable does not contain any value - c#

I have a class called ClassModel. This is how it looks.
class ClassModel
{
dynamic ConnListInstance;
public ClassModel() {
ConnListInstance = Activator.CreateInstance(Type.GetTypeFromProgID("PCOMM.autECLConnlist"));
}
public void checkCount() { //this shows a count of 0
Console.WriteLine(ConnListInstance.Count());
}
public void checkCountVersionTwo() { //this shows a count of 1
ConnListInstance = Activator.CreateInstance(Type.GetTypeFromProgID("PCOMM.autECLConnlist"));
Console.WriteLine(ConnListInstance.Count());
}
}
I have instantiated the class in my main page by declaring ClassModel obj = new ClassModel().
But when I try calling the checkCount method, it returns 0 instead of 1. The checkCountVersionTwo returns 1 but only because I have added the instantiation from the constructor.
Is there something wrong with the way I have created my constructor and class? May I know why it is returning a null/empty value? Shouldn't the variable ConnListInstance have a value upon creating a new ClassModel object?

This has nothing to do with your code, but the reason is in the way how this object works.
Please read the documentation:
An autECLConnList object provides a static snapshot of current
connections. The list is not dynamically updated as connections are
started and stopped. The Refresh method is automatically called upon
construction of the autECLConnList object. If you use the
autECLConnList object right after its construction, your list of
connections is current. However, you should call the Refresh method in
the autECLConnList object before accessing its other methods if some
time has passed since its construction to ensure that you have current
data. Once you have called Refresh you may begin walking through the
collection
(emphasis mine)
So the solution is:
public void checkCount()
{
ConnListInstance.Refresh();
Console.WriteLine(ConnListInstance.Count());
}

Is this the complete code without any other manipulation anywhere?
Ad per this, following seem the case. Please add further code to clarify.
In constructor, you will have a valid instance, unless the CreateInstance fails for some reason
In 1st check method, you will get the count of whatever entity it holds (from construction time to method call time).
In 2nd check method, you are recreating the object and again retrieving its count in same block. So any possible time for entity's to be added to list is within the constructor of ConnListInstance.
Hence, for #2, it seems that you are manipulating the underlying data being contained and hence the list count is reported as 0; whereas at time of fresh construction, it's reported as 1.

Related

How to delete an object on c#?

Is it possible if we delete an object from the class itself? I have a class like below:
Parent Class:
public class ModelBase<T>
{
.....
public void Delete()
{
this = null // <-- it's not works
}
.....
}
Children Class:
public class Company : ModelBase<Company>
{
public string Name;
public Company(string name)
{
Name = name;
}
}
Declaring on UI Layer:
var company = new Company("Company X");
Console.WriteLine(company.Name);
company.Delete();
Console.WriteLine(company.Name); // <-- this should be empty or null
Deleting the object should be on parent class. Is it possible to do that?
No, in C# the garbage collection does the "deleting" for you eventually.
If there`s something inside the class you want to manually dispose like a connection you can use the Disposable Pattern (https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/dispose-pattern).
The closest you can come to manually deleting the object is forcing the garbage collector to collect with GC.Collect (https://msdn.microsoft.com/en-us/library/xe0c2357(v=vs.110).aspx).
Obviously setting this to null inside Delete function has not effect outside of the function (if it ever compile).
Destroying an object from itself is also very dangerous as you would have to be sure that no code afterward would access that object (or the caller stack). IN fact, in C#, the idea does not make more sense as it is garbage collected which imply that if you are inside a member function, then you have at least one reference to the object in which case it would never be garbage collected at that point anyway.
Also assuming that the object company was destroyed (and company set to null), you would get a null pointer exception when calling .Name.
Assuming that company object is not disposable (does not implement IDisposable), then your code should look like:
var company = new Company("Company X");
Console.WriteLine(company.Name);
company = null;
Console.WriteLine(company?.Name); // <-- this should be empty or null
Well, we assume that real code is somewhat more complex than that as otherwise you could simply replace last line by:
Console.WriteLine();
However if you company object implement IDisposable, then usually you should use the using keyword if which case setting the object to null would not make sense.
using (var company = new Company("Company X"))
{
Console.WriteLine(company.Name);
}
Console.WriteLine();
Your Delete function is really a bad idea and clearly show a lack of understanding of C#.
If you want to know if an object has been destroyed, you could use WeekReference. As an example, it can be used for a cache. See reference documentation for more information: https://msdn.microsoft.com/en-us/library/system.weakreference(v=vs.110).aspx.
Your whole code make little sense. If you have only one variable, then it is trivial for a decent programmer to know when the object is alive. If you have multiple objects, then you should use a collection (for ex. List<Company>) in which case, you would obviously remove a company from the collection if you don't want it anymore and then when you use that collection, you would not see it anyway.
Alternatively for complexe cases, you might use a dictionary, a set or a flag to remember if you should process a given object. This might be useful for example when iterating a collection as usually you should not modifying while you are enumerating its items.

What side effects could happen from clearing a list before setting it to a new collection?

I have inherited some code. I see that this code exists:
private List<int> Data { get; set; }
private CsClipboard()
{
Data = new List<int>();
}
public List<int> ComponentIDs
{
get
{
return Data;
}
set
{
Data.Clear();
Data = value;
}
}
I don't see any reason to call clear before setting Data to value. I'm wondering if there are scenarios in C# where I would want to call clear before setting the value aside from something like triggering an OnClear event. It's a fairly large code base with tech. debt, so just being overly cautious.
That code could have some nasty side affects.
What happens there is that the original list gets cleared. so every other place in the code that holds the original list will now hold an empty list.
Every new get request will hold the new list. But the the data isn't concurrent across the program.
In general, you should avoid public properties that return a mutable list. Once a consumer gets a reference to it, you no longer have a guarantee on the state of what should be an internal detail. Clearing the list in a setter only exacerbates the issue, because now you are clearing a list that a consumer might still have a reference to (even though it is no longer the correct list.)
You should consider changing the property so that it returns a copy (preferably read-only) of the current state of the list. The AsReadOnly() method can help here. If you can't do that, at least don't clear the list before setting the new value.
I would want to call clear before setting the value aside from
something like triggering an OnClear event.
The List class does not have events MSDN
So how about writing you own custom Clear method for the list
I mean extension method for the list class that will use your Clear method with your custom logic

In C#, Do events keep a reference to the entire class where the call back method is located?

i have a class that has a ConcurrentDictionary as a private member.
This class also defines a delegate/call back method.
The base class registers this method as the callback for an external event. this is one only ONCE.
I am running ANT memory profiler and i'm seeing 1000s of instances of MyObj referenced from hundreds of instances of the ConcurrentDictionary property. The GC root for these is the event callback.
This seems to be causing memory to rise significantly as the application runs..after maybe about 5 min or so, a good portion of that memory is reclaimed, but i'm worried that the app could potentially run into issue since it swells sto quickly and for so long before GC kicks in.
What's going on here and how do i resolve?
This is a snippet of the base calls that registers the handler
protected abstract void DataReceivedEventHandler(DataChangedEvent evt);
public virtual void RegisterForChanges(ICollection<MemoryTable> tables)
{
foreach (MemoryTable table in tables)
{
_subscribedTables.Add(table);
table.RegisterEventListener(new DataChangedCallBack(this.DataReceivedEventHandler));
}
}
Here is the handler which is implemented in a subclass of the above mentioned baseclass:
private ConcurrentDictionary<string, DataRecord> _cachedRecords;
protected override void DataReceivedEventHandler(DataChangedEvent evt)
{
DataRecord record = evt.Record as DataRecord;
string key = record.Key;
if (string.IsNullOrEmpty(key)) { return; }
if (_cachedRecords.ContainsKey(key))
{
_cachedRecords[key] = record;
DateTime updateTime = record.UpdateTime;
TimeSpan delta = updateTime - _lastNotifyTime;
if (delta.TotalMilliseconds > _notificationFrequency)
{
PublishData(updateTime);
}
}
}
The publishData method publishes prism events
What's going on
Yes, events are a list of delegates, which have two relevant fields: target and method. Unless you are referencing a static method, target is a reference to the class. And method is a reflection MemberInfo which tells the event which method to call.
How to troubleshoot
Consider putting a breakpoint in the add_EventName method. (If you don't have an explicit add_EventName and remove_EventName, you would have to redefine your event with this explicit code).
private event EventHandler eventName;
public event EventHandler EventName
{
add { eventName += value; } // Breakpoint here
remove { eventName -= value; }
}
This will help you find why it is subscribed so many times.
A delegate contains a strong reference to an object along with an indication of what method to call on that object. A live object which holds a strong reference to a delegate will thus keep alive the object upon which the delegate will operate (as well as any objects to which that object holds strong references).
Sometimes one will wish to register a callback or event which will operate on an object for the benefit of some other object, but the callback or event shouldn't keep the object alive solely for its own sake. For example, an object might wish to keep a count of how many times some long-lived object raises a particular event, and thus create an instance of an "event counter" object which it attaches to the event. As long as the long-lived object holds the event subscription for the counter object, that counter object will be kept alive and the counter will get incremented every time the event is raised. Of course, if everybody who would ever have looked at the counter has ceased to exist, neither the counter, nor the effort required to increment it, will serve any useful purpose.
If one has a callback which one expects will be fired at some definite point in the future, but the callback would only serve a useful purpose if some live reference (outside the callback itself) exists to the object upon which it would operate, it may be useful to have the callback registered to a forwarding object which would in turn forward the call to the main object if doing so would make sense. The simplest way to accomplish that is to have the forwarding object hold a WeakReference. When the forwarding object receives a call, it retrieves the Target from the WeakReference. If that's non-null, it casts the retrieved target to the main object's type and calls the appropriate method on it. If the main object ceases to exist before the callback executes, the WeakReference.Target property will be null, and the forwarding object's callback will simply return silently.
A couple of further notes: (1) it might be tempting to set the Target of the WeakReference to a delegate and call that, but that approach will only work if the real target object itself holds a reference to that delegate; otherwise, the delegate itself will be eligible for garbage-collection even if its target isn't; (2) it may be helpful to cast the WeakReference to an interface, and have the main object implement that interface. This would allow one forwarding-object class to be used with many other classes. If one class might want to be attached to a number of weak events, it may be helpful to use a generic interface:
interface IDispatchAction<DummyType,ParamType>
{
void Act(ParamType ref param);
}
That would allow the main object to expose a number of IDispatchAction actions (e.g. if if a class implements IDispatchAction<foo,int>.Act and IDispatchAction<bar,int>.Act, then casting a reference to that class to one of those interfaces and calling Act upon it will invoke the appropriate method).
After the external event is raised the one time, unsubscribe your class from it (SomeClass.SomeEvent -= MyEventHandler), or you can look at using WeakReferences
Is it possible that you are re-subscribing tables over and over again? I see this:
foreach (MemoryTable table in tables)
{
_subscribedTables.Add(table);
table.RegisterEventListener(new DataChangedCallBack(this.DataReceivedEventHandler));
}
and I'd expect to see a check to make sure that tables are not being re-subscribed:
foreach (MemoryTable table in tables)
{
if (!_subscribedTables.Contains(table)) {
_subscribedTables.Add(table);
table.RegisterEventListener(new DataChangedCallBack(this.DataReceivedEventHandler));
}
}
EDIT: Given the comments at the beginning of the question, I am fairly confident that the problem (if you can call it a problem) lies here:
if (_cachedRecords.ContainsKey(key))
{
_cachedRecords[key] = record;
What you are saying here is that if the record's key already exists in cachedRecords, then replace the value with the (presumably) new row instance. This is probably because some background process caused the row's data to be changed and you need to propagate those new values to the UI.
My guess is that the MemoryTable class is creating a new instance of DataRecord for these changes, and sending that new instance up the event chain to the handler we see here. If the event is fired thousands of times, then of course you are going to end up with thousands of them in memory. The garbage collector is usually pretty good about cleaning these things up, but you might want to consider in-place updates to avoid the massive GC that will occur when these instances get collected.
What you should not do is try to control (or even predict) when the GC is going to run. Just make sure that after the GC collects, the excess objects are gone (in other words, make sure that they are not being leaked) and you will be alright.
If we want that the object defined callback method should not stay in memory, we have to define this method as Static.

Difference between Events and Methods

I have some confusion regarding Events. What are the basic differences between C# Events and Methods?
A method is simply code contained within a class to implement a piece of functionality. All code in C# is contained within methods.
As for events, well, suppose you had a simple class which implemented a counter (lets call it the Counter object). Now suppose you wanted to let other objects unrelated to Counter know when the count reached 100. How would you do it?
A logical way would be to allow the other objects to specify one of their own methods they want to be called when the count reaches 100. Each object could then, individually, tell the Counter object which method they want to be called. The Counter object saves this list of methods and, when the count reaches 100, calls each of the saved methods in turn.
This is the how Events work - the Counter class contains an event member (called say, CounterIs100) which other object instances link one of their own methods to. When the Counter object detects that it has has reached 100, it invokes the CounterIs100 member which, automatically, calls all the methods currently linked to it, thus notifying each object in turn that the count has indeed reached 100.
If no objects have linked a method to the CounterIs100 event member, it will be null, so there is no need for the Counter object to invoke the event member.
class Counter
{
// this is the count field used to save the current count value
private int count;
// this is the event member which holds all the methods other objects have specified
public event CounterIs100Delegate CounterIs100;
// This is a method. It invokes the CounterIs100 event member if anyone has subscribed to it
protected void OnCounterIs100()
{
// see if anyone has subscribed (linked) their method to this event
if (CounterIs100 != null)
{
// invoke the event - this will call all subscribed methods
CounterIs100();
}
}
// This is a method. It increments the counter variable stored by this object
public void Increment()
{
count++;
// if the count is 100, invoke the event
if (count == 100)
OnCounterIs100();
}
}
// This is a delegate. It is used to define a template for other objects wishing to
// subscribe to the CounterIs100 event. The methods other objects link to the
// CounterIs100 event must match this declaration (although the name can be changed)
public delegate void CounterIs100Delegate();
// This is a class, unrelated to Counter, but uses its events
class SiteHits
{
Counter hitCounter = new Counter();
public SiteHits()
{
// We want to know when the number of site hits reaches 100.
// We could monitor this ourselves, but we know the Counter class already
// does this, so we just link our method to its event
hitCounter.CounterIs100 += this.WhenSiteHitsReaches100;
}
public void PageRequested()
{
// someone has requested a page - increment the hit counter
Console.WriteLine("We've been hit!");
hitCounter.Increment();
}
// this is the method we want called when the CounterIs100 event occurs.
// note that the return value and parameters match CounterIs100Delegate above.
public void WhenSiteHitsReaches100()
{
Console.WriteLine("Woohoo! We've reached 100 hits!");
}
}
C# Events are a specific form of delegates. If you have programmed in other languages, like C++, you could compare a delegate to a function ("method") pointer - it points to some code in memory. When you call the pointer as a method, you actually call the method at the address the pointer points to.
This is necessary to provide decoupling between the caller and the callee - so you don't have to have all methods ready when you publish code that calls them (which, wouldn't be possible - the Forms controls developers can't possibly know the code that needs to be called when a Button is pressed). You call the pointer, and the other developer sets it to an appropriate memory address later.
P.S. delegates and Events however, have other advantages over plain function pointers - you can be sure that it will point to a good-looking method, taking the correct number and type of arguments and returning the correct type.
An event in C# is a way for a class to provide notifications to clients of that class when some interesting thing happens to an object.
http://msdn.microsoft.com/en-us/library/aa645739%28v=vs.71%29.aspx
A method is a code block containing a series of statements. In C#, every executed instruction is done so in the context of a method.
http://msdn.microsoft.com/en-us/library/ms173114%28v=vs.80%29.aspx
An event in .net is a pair of methods, one for "Add" and one for "Remove", each of which accepts a delegate. Typically, the "Add" method will take the passed-in delegate and add it to either a list of delegates or a MulticastDelegate; passing a delegate to the "Remove" event which was previously passed to the "Add" method should remove that delegate from the list. If one doesn't request otherwise, both C# and vb.net will by default automatically create "Add" and "Remove" events which will behave as indicated above.
This is from MSDN:
An event in C# is a way for a class to provide notifications to clients of that class when some interesting thing happens to an object.
http://msdn.microsoft.com/en-us/library/aa645739%28v=vs.71%29.aspx
A method is a code block containing a series of statements. In C#, every executed instruction is done so in the context of a method.
http://msdn.microsoft.com/en-us/library/ms173114%28v=vs.80%29.aspx

Are .Net property setters ever called implicitly?

I'm on an ASP.Net 2.0 project, in C#. I have some data that gets stored in session state. For ease of use, it is wrapped in a property, like this:
protected IList<Stuff> RelevantSessionData
{
get
{
return (IList<Stuff>) Session["relevant_key"];
}
set
{
Session["relevant_key"] = value;
}
}
Getting and setting the value works exactly as you'd expect. If I want to clear the value, I just set it to null, and there are no problems. However, in another developer's page, he calls the collection's Clear() method. I thought this would be a bug, but it seems to work, and I don't understand why. It works like so:
Debug.WriteLine(RelevantSessionData.Count); //outputs, say, 3
RelevantSessionData.Clear();
Debug.WriteLine(RelevantSessionData.Count); //outputs 0
Why does this work? My naive expectation would be that the middle line loads the serialized value from session, deserializes into an object, calls Clear() on that object, and then lets the unnamed object fall out of scope. That would be a bug, because the value stored in Session would remain unchanged. But apparently, it's smart enough to instead call the property setter and serialize the newly changed collection back into session.
This makes me a little nervous, because there are places in our legacy code where property setters have side effects, and I don't want those getting called if it's not intended.
Does the property setter always get called in a situation like this? Is something else going on? Or do I completely misunderstand what's happening here?
[Added to explain answer]
It turns out did misunderstand. I knew that objects stored in Session must be serializable, and based on that I made too many assumptions about how the collection behaves internally. I was overthinking.
There is only one instance of the stored object (my IList). Each call to the getter returns a reference to that same instance. So the quoted code above works just as it appears, with no special magic required.
And to answer the title question: No, setters are not called implicitly.
Yes, you are right, this would be a bug if your setter/getters were serializing/deserializing the objects. But this is not the case. Instead you are passing based on reference.
So what's basically happening is that the first line in your example gets the item via the get, and Count is called based on that. Then the seccond line is going out and calling get again, returning the same object, running clear, and then the third line is doing the same as the first.
If you had written your setter/getter something like this, you would have a "bug"
protected IList<Stuff> RelevantSessionData
{
get
{
return (IList<Stuff>) JSON.ConvertFromString(Session["relevant_key"]);
}
set
{
Session["relevant_key"] = JSON.ConvertToString(value);
}
}
In this case, a new object would be created and for each call to the get block. But since your example above is simply passing around the reference to the same object, you're not going to see this "bug".
And I say "bug" since it's not really a bug, it's just more of a misunderstanding of what's happening behind the scenes.
I hope this helps.
Your code is roughly equivalent to:
Debug.WriteLine(((IList<Stuff>) Session["relevant_key"]).Count); //outputs, say, 3
((IList<Stuff>) Session["relevant_key"]).Clear();
Debug.WriteLine(((IList<Stuff>) Session["relevant_key"]).Count); //outputs 0
Even if you only call the getter, you are clearing the collection. So the debug output seems normal.
You can expect property setters to be called if:
The are publicly visible (visible to other assemblies).
They implement the setter as part of an interface visible to other assemblies. In some cases, such as
They are used in WPF binding (but the framework will follow the rules about the BindingMode).
They are used in MEF with the ImportAttribute.
They are used in some other binding framework (you get the idea).
You shouldn't run into problems if, for interfaces defined by others, you meet the pre- and post-conditions of the operation.
Edit: I agree with the above. My first choice for exposing a collection is:
private readonly List<T> _sources = new List<T>();
/* Or ICollection<T>, ReadOnlyCollection<T>, or IList<T>, or
* (only a real option for `internal` types) List<T>
*/
public IEnumerable<T> Sources
{
get
{
return _sources;
}
}
If you absolutely must initialize the list after the object is created, then you can use something like this as the second option:
public IList<T> Sources
{
get;
private set;
}
There are situations where the above practices aren't necessarily the best answer, but these are the two most common (IMO?).

Categories

Resources