I don't do .net, but Java has always had abstract classes. In the viewpoint of OOP abstract gives you this advantage...
abstract class Fish {
...
abstract void speak() { }
////
public class SaltwaterFish extends Fish{
...
public void speak() {
I live in the ocean.
}
////////
public class FreshWaterFish extends Fish {
...
public void speak() {
I live in the river.
}
/////
public class Trout extends FreshWaterFish{
...}
public class Tuna extends SaltWaterFish{
...}
//// driver class
public class Aquarium {
// and here is the advantage
Fish[] fishes = new Fish[ 5 ];
fishes[0] = new Trout();
fishes[1] = new Tuna();
fishes[2] = new Tuna();
...
// and then, your for-loop can call a single, common method over TYPES
for( Fish f : fishes )
f.speak();
There are other reasons for abstract, but the above example is one everyone can see easy.