With the problem you're running into here, you can always use typeof
(or perhaps it's a different operator/method) to get the dynamic type of your object. This way you can always perform checks before running into some casting error.
You can set the concrete type restriction to your top-level type, but that really defeats the purpose of generics.
Otherwise, I don't really see how to overcome your problem. If you use generics, the point is to add loose coupling and generic operations that are agnostic on type. The only way you can retrieve it is you typeof and then recast, catching the edge cases to prevent casting errors. Regarding your question:
Can generics be used in a truly loose coupled way?
I don't quite understand what you mean? Semantically from your question, of course you can. That is in fact one of the purposes of generics.
So how would you deal with code that could handle any IFoo derived object and still be able to return a fully formed concrete type regardless of what programmers do down the road?
This is also quite vague. I could write:
public SomeType method(IFoo obj)
{
...
}
And this would still handle any IFoo. You don't need generics for this. If you want to return the type of whatever you passed in concretely, then:
public T method<T>(IFoo obj) where T:IFoo
{
return (T)obj;
}
Hope this helps. LMK if I get something wrong.