The very basic
In .NET, any normal reference to another object is a strong reference. That is, when you declare a variable of a type that's not a primitive/value type, you are declaring a strong reference.
If you hold a strong reference to an object directly in a static variable or in a local variable, it can't be collected. Also, if such an object holds references to other objects, those other objects can't be collected either. That is, an entire graph of objects that have "roots" is considered alive and can't be collected. This is why objects that you are using aren't collected while in use, they are used directly or indirectly through static variables or local variables on the callstack.
So, by knowing what is a strong reference we can understand a weak reference.
A weak reference is a reference to an object that still allows such an object to be collected. In such an event, the weak reference will become null.
The biggest challenge of using a weak reference is to know in which scenarios to use one, as understanding the weak reference itself is not really hard.
When I learned about WeakReferences I immediately thought they were useful for caching. The example of using a WeakReference in MSDN (at least at that moment) was a Windows Forms application that loaded a background image and kept only a weak reference to it. So, if memory was needed, .NET knew it could remove the background from memory, after all such code could reload the background to draw it when needed.
But in the description of the WeakReference itself it is said that WeakReferences aren't good for caching. So, what's wrong?
Read more: Codeproject