Question: How is the loader sure that it is binding the correct assemblies to a program at run time?
Answer: During compilation every assembly gets a version number which is either assigned by the compiler automatically or specified by the programmer in an AssemblyVersion attribute.
If a program P references types from an assembly A the compiler imports the metadata of A and uses them for type checking. The compiler also remembers the version number of A in the assembly generated from P.
When P is loaded the loader asks for the version of the assembly A, which has the version number that was seen during compilation. This makes sure that the assembly which is loaded at run time is the same as the one that the compiler used for type checking.