Form.ShowDialog() and dispose - c#

If I have a method like this:
public void Show()
{
Form1 f = new Form1();
f.ShowDialog();
}
Do I still need to call dispose on the form even though it will go out of scope, which will be eligible for garbage collection.
From some testing, calling this Show() multiple times .. at some point it seems like the GC collects it since I can see the memory spiking then it goes down at some point in time.
From MSDN it seems to say you MUST call dispose when the form is not needed anymore.

What tends to happen is if the item has purely managed resources, calling dispose is not necessarily required, but is strongly advised because it makes disposal deterministic. It isn't always required (in a technical sense) because those managed resources would likely themselves now be eligible for GC, or there is actually nothing to dispose by default and it's an extensibility point.
For unmanaged resources, the Dispose Pattern advises implementing a finalizer, which will be called on GC. If types do not implement the finalizer and dispose is not called, then it is possible (well, very likely) that resources would be left unhandled. Finalizers are the last chance offered by the runtime for clearing your stuff up - they are also time-limited.
Note, that it does not make GC or managed memory reclamation deterministic, disposal is not delete from C++. A disposed item could be a long way away from actually being collected. However, in the managed world, you don't care about deterministic collection, only resource management - in other words, disposal.
That said, I always make sure I call Dispose or use a using statement if a type is disposable, regardless of whether it uses managed or unmanaged resources - it is the expected convention:
public void Show()
{
using (var f = new Form1())
{
f.ShowDialog();
} // Disposal, even on exceptions or nested return statements, occurs here.
}
Update:
After a discussion with Servy I feel I have to express this point as the reasoning behind my advice of disposing where possible. In the case of MemoryStream, it is clearly a disposable type, but actually does not dispose of anything currently.
Relying on this, however, is to rely on the implementation of MemoryStream. Were this to change to include an unmanaged resource, this would then mean that a reliance on MemoryStream not having anything to dispose becomes problematic.
Where possible (as is the case with IDisposable) I prefer to rely on the public contract. Working against the contract in this instance would mean I am safe from underlying implementation changes.

Although you rarely have to manually dispose in C# imo, you could try it like this:
public void Show()
{
using (Form1 f = new Form1())
{
f.ShowDialog();
}
}
Then at the last accolade of the using part it will get disposed of automatically.

ShowDialog has side effect of keeping the GDI objects alive. In order to avoid GDI leak we need to dispose the ShowDialog appropriately. Where as Show method does not have any implication and GDI will be released appropriately. It is recommended to dispose the showDialog and do not rely on Garbage collector.

You could simply do:
using (var f = new Form1())
f.ShowDialog();

If you want to explicitly dispose, use
using(Form1 f = new Form1()){
f.ShowDialog();
}
This ensures Dispose() is called, as well as it occurs immediately

In your specific example, no, it's unlikely that it would be particularly useful. Forms do not hold onto a significant amount of resources, so if it takes a little bit longer for some portion of it's code to get cleaned up it isn't going to cause a problem. If that form just happens to be holding onto a control that is used to, say, play a video, then maybe it's actually holding onto some significant number of resources, and if you actually do dispose of those resources in the dispose method then it's worth taking the time to call dispose. For 99% of your forms though, their Dispose method will be empty, and whether you call it or not is unlikely to have any (or any noticeable) effect on your program.
The reason that it's there is primarily to enable the ability to dispose of resources in those 1% of cases where it's important.
It's also worth noting that when a Form is closed its Dispose method is already being called. You would only ever need to add a using or explicit Dispose call if you want to dispose of a Forms resources before that form is closed. (That sounds like a generally bad idea to me). This is easy enough to test. Just create a project with two forms. Have the second form attach an event handler to the Disposing event and show a message box or something. Then when you create an instance of that form and show it (as a dialog or not) you'll see that when you close it the message box will pop up right away, even if you keep the 'Form' instance around and without you ever needing to add a using or Dispose call.

Yes, you need and MUST call Dispose or use using statement, otherwise it can be, that instance remains in memory.
You can check it, if you put a Timer to the form and set a break point in the Timer.Tick handler. Even after closing the form without Dispose the handler will be called.

Related

Calling dispose within list.removeAll

I'm pretty new to C# programming, and the concept of the GC, and its realtions to IDisposable is still a bit vague. What does calling Dispose mean in terms of the garbage collection?
Specifically i wonder if the following code may fail occationally, depending on when the garbage collection kicks in. (I have not been able to make it crash during my tests).
//List<TestClass2> tc2List;
//TestClass2 invokes a thread. It implements IDisposable.
//Its Dispose() sets a stop-condition for the thread,
//and joins the thread, awaiting it to stop. (may take 100 msek)
tc2List.RemoveAll(t =>
{
if (String.Compare(t.Name, "Orange") == 0)
{
t.Dispose(); //May take up to 100 msek
return true;
}
return false;
});
Your code works, but it's bad style. Predicates should not have side effects. So you should first dispose the elements, and then remove them.
Predicate<T> filter = t => t.Name == "Orange";
foreach(var t in tc2List.Where(filter))
t.Dispose();
tc2List.RemoveAll(filter);
i wonder if the following code may fail occationally, depending on when the garbage collection kicks in
No, it won't fail
//Its Dispose() sets a stop-condition for the thread,
//and joins the thread, awaiting it to stop. (may take 100 msek)
That is a slightly a-typical use of Dispose() but not wrong. A more efficient approach would use a different Stop() so that you can stop all threads at once. Or call Dispose() from Parallel.ForEach(). But whatever method you choose, it is not hindering, nor is it being hindered by, the GC.
Do you have finalize method in you TestClass2?
Dispose main properties
This has to be implemented in classes implementing IDispose interface.
Its the right place for freeing-up unmanaged resources like file, handles, and connections etc.
Dispose() method is called explicitely in the code itself.
Dispose() method is automatically called (for objects which implement IDispose), when used in a "using"
Refer to link.
What does calling Dispose mean in terms of the garbage collection?
Calling dispose, means you are forcibly cleaning up things (literally the memory) using your implementation of the Dispose method. Note : (Some of the framework classes do call your implementation of Dispose for you. System.Windows.Forms.Form for example)
Garbage collection on the contrast is a feature of the .NET runtime that will clean up things for you automatically. Automatically i mean, because its up to the memory pressure and other factors that is taken care by the runtime.
A simple strategy i would recommend. Do Dispose() if you think that the memory would stay longer than needed and would impact the application. Else leave it to the runtime, it will automatically cleans up (i.e finalizes) the objects when they go out of scope. The GC has its own algorithm on how to do cleanup, but you can to a greater extent rely on it.
The next question
Specifically i wonder if the following code may fail occasionally, depending on when the garbage collection kicks in
I guess no. Failure of the code due to GC kicking in, depends on how you write the finalizer of TestClass2. Definitely your call t.Dispose() wont clash with the GC.

For Microsoft built classes that inherit IDisposable, do I explicitly have to call Dispose?

Regarding the Microsoft built classes that inherit IDisposable, do I explicitly have to call Dispose to prevent memory leaks?
I understand that it is best practice to call Dispose (or better yet use a using block), however when programming, typically I don't always immediately realise that a class inherits from IDisposable.
I also understand that Microsoft implementation of IDisposable is a bit borked, which is why they created the article explaining the correct usage of IDisposable.
Long story short, in which instances is it okay to forget to call Dispose?
There are a couple of issues in the primary question
Do I explicitly have to call Dispose to prevent memory leaks?
Calling Dispose on any type which implements IDisposable is highly recomended and may even be a fundamental part of the types contract. There is almost no good reason to not call Dispose when you are done with the object. An IDisposable object is meant to be disposed.
But will failing to call Dispose create a memory leak? Possibly. It's very dependent on what exactly that object does in it's Dispose method. Many free memory, some unhook from events, others free handles, etc ... It may not leak memory but it will almost certainly have a negative effect on your program
In which instances is it okay to forget to call Dispose?
I'd start with none. The vast majority of objects out there implement IDisposable for good reason. Failing to call Dispose will hurt your program.
It depends on two things:
What happens in the Dispose method
Does the finalizer call Dispose
Dispose functionlity
Dispose can do several type of actions, like closing a handle to a resource (like file stream), change the class state and release other components the class itself uses.
In case of resource being released (like file) there's a functionality difference between calling it explicitly and waiting for it to be called during garbage collection (assuming the finalizer calls dispose).
In case there's no state change and only components are released there'll be no memory leak since the object will be freed by the GC later.
Finalizer
In most cases, disposable types call the Dispose method from the finalizer. If this is the case, and assuming the context in which the dispose is called doesn't matter, then there's a high chance that you'll notice no difference if the object will not be disposed explicitly. But, if the Dispose is not called from the finalizer then your code will behave differently.
Bottom line - in most cases, it's better to dispose the object explicitly when you're done with it.
A simple example to where it's better to call Dispose explicitly: Assuming you're using a FileStream to write some content and enable no sharing, then the file is locked by the process until the GC will get the object. The file may also not flush all the content to the file so if the process crashes in some point after the write was over it's not guaranteed that it will actually be saved.
It can be safe to not call Dispose, but the problem is knowing when this is the case.
A good 95% of IEnumerator<T> implementations have a Dispose that's safe to ignore, but the 5% is not just 5% that'll cause a bug, but 5% that'll cause a nasty hard to trace bug. More to the point, code that gets passed an IEnumerator<T> will see both the 95% and the 5% and won't be able to dynamically tell them apart (it's possible to implement the non-generic IEnumerable without implementing IDisposable, and how well that turned out can be guessed at by MS deciding to make IEnumerator<T> inherit from IDisposable!).
Of the rest, maybe there's 3 or 4% of the time it's safe. For now. You don't know which 3% without looking at the code, and even then the contract says you have to call it, so the developer can depend on you doing so if they release a new version where it is important.
In summary, always call Dispose(). (I can think of an exception, but it's frankly too weird to even go into the details of, and it's still safe to call it in that case, just not vital).
On the question of implementing IDisposable yourself, avoid the pattern in that accursed document.
I consider that pattern an anti-pattern. It is a good pattern for implementing both IDisposable.Dispose and a finaliser in a class that holds both managed and unmanaged resources. However holding both managed IDisposable and unmanaged resources is a bad idea in the first place.
Instead:
If you have an unmanaged resource, then don't have any unmanaged resources that implement IDisposable. Now the Dispose(true) and Dispose(false) code paths are the same, so really they can become:
public class HasUnmanaged : IDisposable
{
IntPtr unmanagedGoo;
private void CleanUp()
{
if(unmanagedGoo != IntPtr.Zero)
{
SomeReleasingMethod(unmanagedGoo);
unmanagedGoo = IntPtr.Zero;
}
}
public void Dispose()
{
CleanUp();
GC.SuppressFinalize(this);
}
~HasUnmanaged()
{
CleanUp();
}
}
If you have managed resources that need to be disposed, then just do that:
public class HasUnmanaged : IDisposable
{
IDisposable managedGoo;
public void Dispose()
{
if(managedGoo != null)
managedGoo.Dispose();
}
}
There, no cryptic "disposing" bool (how can something be called Dispose and take false for something called disposing?) No worrying about finalisers for the 99.99% of the time you won't need them (the second pattern is way more common than the first). All good.
Really need something that has both a managed and an unmanaged resource? No, you don't really, wrap the unmanaged resource in a class of your own that works as a handle to it, and then that handle fits the first pattern above and the main class fits the second.
Only implement the CA10634 pattern when you're forced to because you inherited from a class that did so. Thankfully, most people aren't creating new ones like that any more.
It is never OK to forget to call Dispose (or, as you say, better yet use using).
I guess if the goal of your program is to cause unmanaged resource leaks. Then maybe it would be OK.
The implementation of IDisposable indicates that a class uses un-managed resources. You should always call Dispose() (or use a using block when possible) when you're sure you're done with the class. Otherwise you are unnecessarily keeping un-managed resources allocated.
In other words, never forget to call Dispose().
Yes, always call dispose. Either explicitly or implicitly (via using). Take, for example, the Timer class. If you do not explicitly stop a timer, and do not dispose it, then it will keep firing until the garbage collector gets around to collecting it. This could actually cause crashes or unexpected behavior.
It's always best to make sure Dispose is called as soon as you are done with it.
Microsoft (probably not officially) says it is ok to not call Dispose in some cases.
Stephen Toub from Microsoft writes (about calling Dispose on Task):
In short, as is typically the case in .NET, dispose aggressively if
it's easy and correct to do based on the structure of your code. If
you start having to do strange gyrations in order to Dispose (or in
the case of Tasks, use additional synchronization to ensure it's safe
to dispose, since Dispose may only be used once a task has completed),
it's likely better to rely on finalization to take care of things. In
the end, it's best to measure, measure, measure to see if you actually
have a problem before you go out of your way to make the code less
sightly in order to implement clean-up functionality.
[bold emphasize is mine]
Another case is base streams
var inner = new FileStrem(...);
var outer = new StreamReader(inner, Encoding.GetEncoding(1252));
...
outer.Dispose();
inner.Dispose(); -- this will trigger a FxCop performance warning about calling Dispose twice.
(I have turned off this rule)

C# - Are objects immediately destroyed when going out of scope?

Can I trust that an object is destroyed and its destructor is called immediately when it goes out of scope in C#?
I figure it should since many common coding practices (e.g. transaction objects) rely on this behaviour, but I'm not very used to working with garbage collection and have little insight to how such languages usually behave.
Thanks.
Nope, .Net and hence C# relies on a garbage collection memory management. So destructors (which in .Net is called finalizers) are not called until GC finds it proper to destroy the objects.
Additionally: most "regular" objects in C# don't have destructors. If you need the destructor pattern you should implement the IDisposable interface with the Dispose Pattern. On disposable objects you should also make sure that the Dispose method gets called, either with the using keyword or directly calling the method.
To further (hopefully) clarify: deterministic disposal is useful in .Net e.g. when you need to explicitly free resources that is not managed by the .Net runtime. Examples of such resources are file handles, database connections, etc. It is usually important that these resources be freed as soon as they no longer are needed. Thus we cannot afford to wait for the GC to free them.
In order to get deterministic disposal (similar to the scope behavior of C++) in the non-deterministic world of the .Net GC, the .Net classes rely on the IDisposable interface. Borrowing from the Dispose Pattern, here are some examples:
First, instantiating a disposable resource and then letting the object go out of scope, will leave it up to the GC to dispose the object:
1. {
2. var dr = new DisposableResource();
3. }
To fix this we can explicitly dispose the object:
1. {
2. var dr = new DisposableResource();
3.
4. ...
5.
6. dr.Dispose();
7. }
But what if something goes wrong between line 2 and 6? Dispose will not be called. To further ensure that Dispose will finally be called regardless of any exceptions we can do the following:
1. var dr = new DisposableResource();
2. try
3. {
4. ...
5. }
6. finally
7. {
8. dr.Dispose();
9. }
Since this pattern is often needed, C# includes the using keyword to simplify things. The following example is equivalent to the above:
1. using (var dr = new DisposableResource())
2. {
3. ...
4. }
No. An object doesn't actually go "out of scope," the reference to it (i.e. the variable you use to access it) does.
Once there are no more references to a given object, that object becomes eligible for garbage collection (GC) should the need arise. Whenever the GC decides it needs to reclaim the space your no-longer-referenced object, that's when the objects finalizer will be called.
If your object is a resource (e.g. a file handle, database connection), it should implement the IDisposable interface (which obligates the object to implement a Dispose() method to clean up any open connections, etc). The best practice for you in this case would be to create the object as part of a using block, so that when this block is completed, your application will automatically call the objects Dispose() method, which will take care of closing your file/db connection/whatever.
e.g.
using (var conn = new DbConnection())
{
// do stuff with conn
} // conn.Dispose() is automatically called here.
The using block is just some syntactic sugar which wraps your interactions with the conn object in a try block, along with a finally block which only calls conn.Dispose()
There is no such thing als a C++-like destructor in C#. (There is a different concept of destructor in C#, also called a finalizer, which uses the same syntax as C++ destructors, but they are unrelated to destroying objects. They're intended to provide a cleanup mechanism for unmanaged resources.)
The garbage collector will cleanup objects sometime after they are no longer referenced. Not immediately, and there is no way to guarantee this either.
Luckily there is also no real reason why you would want to guarantee this. If you need the memory, then the GC will reclaim it then. If you don't, why care if there's still some garbage object around? It's not a memory leak: the GC can still find it and clean it up any time.
No, this isn't guaranteed. Similar to languages such as Java, in C# the garbage collector runs when it's needed (i. e. when the heap is getting too full). However, when your objects implement IDisposable, i. e. they have a Dispose() method and it has to be called, then you can take advantage of the using keyword:
using (var foo = new DisposableObject()) {
// do something with that
}
That way Dispose() will be called immediately when leaving that using block.
Note: IDisposable is found in many types, most notably GDI+ but also database connections, transactions, etc. so it may really be the right pattern here.
Note 2: Behind the scenes above block will get translated into a try/finally block:
var foo = new DisposableObject();
try
{
// do something with that
}
finally
{
foo.Dispose();
}
But that translation is done by the compiler and very handy for not forgetting to call Dispose().
I don't think you should rely on garbage collectors in this way. Even if you deduct how they operate it might very well be that in the next release they've reimplemented it.
In any case, objects are not garbage collected the moment you unreference them. Typically they are collected until some threshold is reached and then they are released.
Especially in java programs this is very noticeable when you look at the memory consumption on the task manager. It grows and grows and all of a sudden every minute it drops again.
No. If you refer to CLI specification (p. 8.9.6.7 about Finalizers) http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-335.pdf you can find the following
the CLI should ensure that finalizers are called soon after the instance becomes
inaccessible. While relying on memory pressure to
trigger finalization is acceptable, implementers should consider the use of additional
metrics
but it must not.

Disposing of System.Drawing Objects

Is it necessary to manually manage the lifetime of System.Drawing objects?
Currently I am employing 'using' statements to minimise the lifespan of Brushes and other Drawing objects e.g.
using ( Brush br = new SolidBrush( color ) )
{
// Do something with br
}
Is this necessary or is it safe to let the garbage collector work its magic when and if it needs to?
As a quick aside to the question... what do people think is the cleanest way to achieve this?
When an object is IDisposable, then it is better to dispose it as soon as you do not need it any more. (It implements IDisposable for a reason).
Offcourse, when you forget to call Dispose, the Garbage collector will do its work at some time, and clean it up, so that resources are freed, but you can never tell or guess when the Garbage Collector will kick in, it is not deterministic.
So, my advice is: call Dispose manually (like you're doing now) as soon as you do not need the disposable object any more.
It is good to Dispose of System.Drawing object, however if you miss one or two when you get an exception etc, it is not the end of the world. (Other objects like opened files and database connections must always be disposed)
Having lots of “Using” statement all over your code make it more complex to understand. I would therefore in the case of System.Drawing object, consider just calling Dispose() on them at the end of the method.
In the past I have used a class I written “Dustcart”, that implements IDisposable, and contains a collection of objects to dispose. You can then write code like:
using(var dustcart = new Dustcard())
{
var p = dustcart.Add(new Pen(red, etc));
var b = dustcart.Add(new Brush(black));
Pen t;
if (someFlag)
{
t = p;
}
else
{
t = dustcard.Add(new Pen(etc));
}
}
The general rule of thumb is that if an object implements IDisposable you need to clean it up. IDisposable is not implemented on a whim in the .NET Framework - There are good reasons for it to be there.
As the others said: when you create an IDisposable object, you should Dispose it as soon as possible. In your specific example, if the color is known at compile time, you could use a standard brush such as Brush br = Brushes.Blue which you don't need to dispose.
If you are re-using the same colour over and over you could store the brush as a class-level member, however this would mean that the owning class should be IDisposable too, and dispose the brush member in it's dispose method.
This would increase the memory storage (by the size of one brush), but might reduce the amount of code (no using statements but an additional Dispose override).
I am using the 'using' statement just as you described in your question to guarantee that the Brush, Pen, Font, whatever resource is disposed of properly. In my code, I find the using statements cleaner than having explicit .Dispose() calls scattered throughout. But that's just my preference.
I agree with the answers above though: regardless of whether you prefer using statements or .Dispose calls, it's pretty important to clean up the resources manually, rather than relying on the garbage collector. (I was relying on the garbage collector at first and performance problems began to surface, even before things in the app were getting complicated.)

How do I track down where I've been leaking IDisposable objects from?

I've been debugging some code recently that was a bit memory leaky. It's a long running program that runs as a Windows service.
If you find a class wearing an IDisposable interface, it is telling you that some of the resources it uses are outside the abilities of the garbage collector to clean up for you.
The reason it is telling you this is that you, the user of this object, are now responsible for when these resources are cleaned up. Congratulations!
As a conscientious developer, you are nudged towards calling the .Dispose() method when you've finished with the object in order to release those unmanaged resources.
There is the nice using() pattern to help clean up these resources once they are finished with. Which just leaves finding which exact objects are causing the leakyness?
In order to aid tracking down these rogue unmanaged resources, is there any way to query what objects are loitering around waiting to be Disposed at any given point in time?
There shouldn't be any cases where you don't want to call Dispose, but the compiler cannot tell you where you should call dispose.
Suppose you write a factory class which creates and returns disposable objects. Should the compiler bug you for not calling Dispose when the cleanup should be the responsibility of your callers?
IDisposable is more for making use of the using keyword. It's not there to force you to call Dispose() - it's there to enable you to call it in a slick, non-obtrusive way:
class A : IDisposable {}
/// stuff
using(var a = new A()) {
a.method1();
}
after you leave the using block, Dispose() is called for you.
"Is there any way to detect at the end of the program which objects are loitering around waiting to be Disposed?"
Well, if all goes well, at the end of the program the CLR will call all object's finalizers, which, if the IDisposable pattern was implemented properly, will call the Dispose() methods. So at the end, everything will be cleared up properly.
The problem is that if you have a long running program, chances are some of your IDiposable instances are locking some resources that shouldn't be locked. For cases like this, user code should use the using block or call Dispose() as soon as it is done with an object, but there's really no way for a anyone except the code author to know that.
You are not required to call the Dispose method. Implementing the IDisposable interface is a reminder that your class probably is using resources such as a database connection, a file handle, that need to be closed, so GC is not enough.
The best practice AFAIK is to call Dispose or even better, put the object in a using statement.
A good example is the .NET 2.0 Ping class, which runs asynchronously. Unless it throws an exception, you don't actually call Dispose until the callback method. Note that this example has some slightly weird casting due to the way Ping implements the IDisposable interface, but also inherits Dispose() (and only the former works as intended).
private void Refresh( Object sender, EventArgs args )
{
Ping ping = null;
try
{
ping = new Ping();
ping.PingCompleted += PingComplete;
ping.SendAsync( defaultHost, null );
}
catch ( Exception )
{
( (IDisposable)ping ).Dispose();
this.isAlive = false;
}
}
private void PingComplete( Object sender, PingCompletedEventArgs args )
{
this.isAlive = ( args.Error == null && args.Reply.Status == IPStatus.Success );
( (IDisposable)sender ).Dispose();
}
Can I ask how you're certain that it's specifically objects which implement IDisposable? In my experience the most-likely zombie objects are objects which have not properly had all their event handlers removed (thereby leaving a reference to them from another 'live' object and not qualifying them as unreachable during garbage collection).
There are tools which can help track these down by taking a snapshot of the managed heap and stacks and allowing you to see what objects are considered in-use at a given point in time. A freebie is windbg using sos.dll; it'll take some googling for tutorials to show you the commands you need--but it works and it's free. A more user-friendly (don't confused that with "simple") option is Red Gate's ANTS Profiler running in Memory Profiling mode--it's a slick tool.
Edit: Regarding the usefulness of calling Dispose--it provides a deterministic way to cleanup objects. Garbage Collection only runs when your app has ran out of its allocated memory--it's an expensive task which basically stops your application from executing and looks at all objects in existance and builds a tree of "reachable" (in-use) objects, then cleans up the unreachable objects. Manually cleaning up an object frees it before GC ever has to run.
Because the method creating the disposable object may be legitimately returning it as a value, that is, the compiler can't tell how the programming is intending to use it.
What if the disposable object is created in one class/module (say a factory) and is handed off to a different class/module to be used for a while before being disposed of? That use case should be OK, and the compiler shouldn't badger you about it. I suspect that's why there's no compile-time warning---the compiler assumes the Dispose call is in another file.
Determining when and where to call Dispose() is a very subjective thing, dependent on the nature of the program and how it uses disposable objects. Subjective problems are not something compilers are very good at. Instead, this is more a job for static analysis, which is the arena of tools like FxCop and StyleCop, or perhaps more advanced compilers like Spec#/Sing#. Static analysis uses rules to determine if subjective requirements, such as "Always ensure .Dispose() is called at some point.", are met.
I am honestly not sure if any static analyzers exist that are capable of checking whether .Dispose() is called. Even for static analysis as it exists today, that might be a bit on the too-subjective side of things. If you need a place to start looking, however, "Static Analysis for C#" is probably the best place.

Categories

Resources