C# doesn't allow you to specify in an interface or abstract class the parameters that a constructor must take: which makes it very difficult to use such classes as generic type arguments for instance. There's a new() constraint which allows you to call a parameterless constructor, and if you also constrain the generic type argument to some interface, you can set the data you want through it.
If you expect parameters in the constructor though, you can't simply create a new object of the type passed as a generic argument. You must use reflection (Activator.CreateInstance(typeof(T) ...), assuming that there exists a constructor for the yet unknown type (obviously not statically checkable). To prove such a constructor exists at runtime, you can use typeof(T).GetConstructors(), and search through the returned collection for a ConstructorInfo with matching arguments. If you get this far, you'll probably drop the idea and resort to the create-set-call mess instead.
I suppose a way of fixing this would be to introduce some kind of "constructor pattern" into interfaces and non-sealed classes, requiring subclasses to implement it and allowing the use of said constructor pattern as a generic type argument constraint.
Another time you might need create-set-call is if constructing objects which have a mutual reference to eachother. [ var a = new A(); var b = new B(a); a.setB(b); ] cannot be expressed with parameters in both ctors. This might seem like a "bad idea" due to the circular reference, but it's more common than you'd think, and doesn't necessarily mean bad code.
void Foo<T>(Func<Int, String, T> makeT) where T : IIface {
T myT = makeT(10, "hi");
// ...
}
Foo((x, y) => new MyClass(x, y));
In patternese, this is injecting a factory dependency.Reflection must be used in that case. Using `new T()` for parameterless ctors is just a call to Activator.CreateInstance<T>(), but there are no generic CreateInstance overloads taking arguments.
1) Hmm, let's see what classes are in this namespace... Ah, this one looks like it might do the job so I'll type
2) Dang, don't want to scroll through tooltips for 23 different constructors with poorly named params, think I'll just use the default constructor, they probably implemented that for casual users like me.3) Now I can type foo. and let IntelliSense give me options. When I call a function I get an error for each call instead of some crazy exception for the whole thing. Maybe I can even test stuff out in the Immediate window in the debugger.
So, I think it's not only miseducation or layzness, it's that modern IDEs for static languages encourage discovery based development in favor of reading through API documents.