HomeController has a dependency on Student because it delegates some responsibility to Student class.
One way to implement is:
public HomeController()
{
private Student _student;
public HomeController()
{
_student = new Student();
}
}
public class Student
{
// Some method
}
but then HomeController has a hard dependency on Student class. What if you wanted to use some other implementation of Student (e.g. wanted to mock Student while unit testing your HomeController). You will have to modify the Student class or HomeController class (or use some other not-so-good option). This means your HomeController is tightly-coupled to Student class.
The other way is the code you have posted:
public class HomeController
{
private IStudent _student;
public HomeController(IStudent student)
{
_student = student;
}
}
public interface IStudent
{
// Some method
}
public class Student : IStudent
{
// Implementation of some method
}
Here, you can pass on any implementation of IStudent i.e. in your unit tests you can pass the mock object of IStudent, in your actual code you will pass object of Student class. So you HomeController is now dependent on the IStudent interface (abstraction) rather than on the Student class (an implementation).
This is inline with the OOP principles:
Program to interfaces, not implementations.
Depend on abstractions. Do not depend on concrete classes.
Also, it now has a soft dependency. It's no longer tightly-coupled to the Student class. It's loosely-coupled.
Now, generally you don't need to worry about which implementation of IStudent you should pass while instantiating your HomeController. That's something the Depedency Injection Container (Unity in your case) will take care of, as long as you register correct interface and classes with it.
_container.Register<IStudent, Student>();
So when a new instance of HomeController is required, the container will identify that an instance of IStudent is required. So it will instantiate the registered instance of IStudent and pass it as paramter while instantiating HomeController class.
Also, note that what you are referring to is 'Dependency Injection' (which is one specific form of IoC). There are other forms of IoC (e.g. callbacks, Observer pattern, etc.).
EDIT:
Don't forget to read the popular article on DI.