The C# langauge requires that all variables be definitely assigned to before they are read from. Local variables are considered to be initially unassigned, whereas fields, array elements, and so on, are considered to be initially assigned to their default value. (Which, for a reference type, is null.)
There is no technical reason why we couldn't treat local variables as initially assigned to their default values and throw away all the definite assignment checking. It's there because using an unassigned local as its default value is (1) a bad coding practice, and (2) a highly probable source of irritating bugs. By requiring you to explicitly assign local variables before they are used, we prevent the user from using a bad practice, and eliminate a whole class of bugs that you then never have to debug.
Also, consider the following:
while(whatever)
{
int i;
print(i);
i = i + 1;
}
Do you expect i to hold its value across executions of the loop, or for it to be initialized fresh to zero every time? By forcing you to explicitly initialize it, the question becomes meaningless and this is a difference which makes no difference.
(Also, in the case above there is a small potential performance optimization, in that the compiler could re-use the variable without having to generate code to clear its contents because the compiler knows that you will clear the contents.)
I don't know how to answer your second question because I don't know what you mean by "work". Can you tell me how assigning "int x = 123;" works? Once I know what you mean by "works" then I can describe how assigning a null to a variable of reference type works.