인터페이스는 '클래스들이 제공하는 메소드들을 미리 정의해놓은 규약'이라고 할 수 있다. 즉, 특정 인터페이스를 구현하는 클래스는 해당 인터페이스가 정의하는 메소드들을 구현해야 한다.
인터페이스와 클래스간에는 '구현'이, 인터페이스간에는 '상속'이라는 표현이 맞다고 생각한다. 하지만, 실수로 인터페이스-클래스간의 관계를 '상속'이라고 해도 넘어가주길 바란다.
실제로 System.Collections에 있는 IList의 정의를 보면 아래사진과 같다.

ICollection과 IEnumerable를 상속받는 IList는 위의 사진에 있는 필드, 메소드와 ICollection과 IEnumerable에 존재하는 필드 및 메소드도 구현해야할 것을 미리 정의한다.
임의로 Stack이라는 클래스를 만들고 IList를 상속받도록하면 빨간줄과 함께 필수 메소드 구현을 하지 않았다는 컴파일 에러가 발생한다. IDE에서 인터페이스를 구현하겠다는 버튼을 클릭하면 아래 사진과 같이 기본 구조가 자동완성된다.

C#에 있는 대부분의 클래스들은 다양한 인터페이스들을 설계하고 설계한 인터페이스를 구현하는 방식으로 만들어졌다.
아래 예제는 IDevice라는 인터페이스와 MediaPlayer라는 클래스가 있고 IDevice를 구현하고 MediaPlayer를 상속받는 PortableDevice라는 클래스를 만든다 할 때 함수 정의는 어떻게 해야하는지를 나타낸다.
interface IDevice
{
// 1) public?
void Activate();
}
class MediaPlayer
{
public virtual void Play() { }
}
class PortableDevice : MediaPlayer, IDevice
{
// 2) override
public override void Play() { }
// 3) override? virtual?
public override void Activate() { }
public virtual void Activate() { }
public void Activate() { }
}
1. IDevice의 Activate 메소드에 public를 붙여야 하는가?
인터페이스의 메소드 앞에 접근지정자를 붙이지 않는다. 하지만, C# 8.0부터는 표기할 수 있다.
2. MediaPlayer를 상속 받는 PortableDevice의 Play 메소드에 override를 붙여야 하는가?
목적이 MediaPlayer의 Play 메소드를 재정의하는 것이라면 붙여야 한다. PortableDevice만의 새로운 Play 메소드를 만드는 것이라면 override 대신 new를 사용해야 한다.
3. IDevice를 구현하는 PortableDevice의 Activate 메소드에는 override를 붙여야 하는가? virtual를 붙인다면? 아무것도 안붙이는 것은?
우선, 메소드를 구현할 때는 override를 표기하지 않는다. 붙인다면 재정의할 메소드를 찾을 수 없다는 컴파일에러가 발생한다.
이외에는 virtual를 붙여도되고 붙이지 않아도 된다. 구현하는 메소드가 가상메소드인지 비가상메소드인지 구분할 뿐이지 실제 구현은 정상적으로 이뤄진다.