4

Is it acceptable to have a dummy generic parameter in the parameters list in order to save method consumers from the need to specify type arguments? For example -

public T Generate<T>(int paramForInstance) where T : MyClass {
    return MyClass.SomeFactoryMethod<T>(paramForInstance);
}

//calling code needs to specify type
MyDerivedClass instance = Generate<MyDerivedClass>(5);

public T Generate<T>(int paramForInstance, T dummy) where T : MyClass {
    return MyClass.SomeFactoryMethod<T>(paramForInstance);
}

//calling code needs to provide a "sample" to enable type inference
MyDerivedClass instance = null;
instance = Generate(5,instance);

The assumption here is that if junior other devs on the team don't need to think about generics, they're less likely to kick.

A Little Background (feel free to skip this)

A couple weeks ago, a management-developer type in my team freaked out when he saw code (my code) that looked like this:

//conversion methods, using generics
private static TResult? IfNotDangerous<TResult>
  (SomeType firstThing, string name, Func<object, TResult?> conversion) 
  where TResult : struct
{
    return IfNotDangerous(firstThing, name, 
          (any, dummy) => conversion(any), (TResult?)null);
}

private static TResult IfNotDangerous<TResult>
  (SomeType firstThing, string name, Func<object, TResult, TResult> conversion,
  TResult defaultValue)
{
    if (firstThing == null) return defaultValue;
    if (!firstThing.Contains(name)) return defaultValue;
    if (firstThing[name] == DangerousValue) return defaultValue;
    return conversion(firstThing[name], defaultValue);
}

The complaint he had was, "Why are you using a struct?! That's so resources-heavy! And what does 'where' mean? Nobody on the senior development end knows what that does - I've asked them all!"

After overcoming my self-pity, I found a way around that didn't use generics for this particular method. Appeasement was achieved. But I'd like to avoid trouble in the future, if possible.

EDIT

I appreciate all the encouragement, but the question was not "should I look elsewhere for work?" - it was "is this a usable workaround?"

sq33G
  • 278

7 Answers7

31

Sad to see programmers that do not move along with the times.

The fact is that generics have been part of C# and .NET since version 2 and LINQ since version 3. These are no longer cutting edge new techniques.

Instead of "Protecting" them you should be teaching them. Start a weekly tutorial (over lunch if you don't have buy-in) for all developers who are interested in staying current.

The fact is that if they bring in a new senior, chances are they would also be using generics and LINQ. Keeping these "hidden" or not using them is a disservice to the other developers and the company.

If you are told to not use generics and LINQ at all, I would sadly conclude it is time to look for a job where developers don't cripple themselves.


Update:

Since you don't seem to think the above answers the question "is this a usable workaround?" I will answer now:

No it isn't. It is an abuse of generics and has too much "magic" - it is even less understandable than the straight generic code and if any of your colleagues will have to delve into it, they will not be able to figure it out.

The fact that it works and does what you want it to (hide the use of generic) is besides the point. It is opaque and even the usage is not idiomatic (giving a "prototype" to the function for it to work).

Oded
  • 53,734
4

From the moment they do not allow you to use the full features of the language (a language which, I presume, was chosen by them, not you,) anything goes. Is it acceptable? Sure it is. I would never do such a thing, but it seems like you have to. And it will work.

But if I were in your shoes I would go all the way with it: I would set the compatibility level of the compiler (in project options) so that language constructs that they consider unacceptable cannot even compile, which would mean that the entire shop would be coding in C# 1.0. And I would start looking for another job.

Mike Nakis
  • 32,803
4

The way I see your question is as follows:

Should I write code which doesn't follow the standard conventions and will teach people who don't know generics bad habits, or should I use them the way they're intended to be used?

Viewed from that perspective, I think it answers itself.

In answer to "What does where mean?" you could send an e-mail linking to http://msdn.microsoft.com/en-us/library/6b0scde8(v=vs.80).aspx explaining that although MS have clearly borked the "Other versions" link, the documentation of where clauses from VS2005 is still valid.

Peter Taylor
  • 4,043
2

The introspection about whether you're making code too complicated or if it is reasonable to expect others to be about to understand and use your code is a good thing. However, on this particular snippet

MyDerivedClass instance = null; 
instance = Generate(5, instance); 

I do not like it. In my view, this does not make the code simpler. And it is obviously no more succinct. You haven't saved the developer from having to specify the class type for the generic method call, you have simply moved where it is specified. Either way, you've explicitly stated the type. You're also making me wonder what the method might be doing with instance, why I am reassigning it, etc. (Keep in mind, someone may very well "new up" or otherwise have an instance prior to the method call.) For an experienced* developer, this might not be a problem. For the junior you are trying to shelter?

No, I would opt for what should be simple enough to reason about.

var instance = Generate<MyDerivedClass>(5); 

You certainly want to make code as easy to read, use, and decipher as possible, but creating overloads with degenerate parameters is not likely the solution.


(*) I have recently been involved in helping to interview candidates for roles on my current team. Let's just say the "experienced developers" aren't nearly as experienced as you and I might desire and they might believe. These developers with 5, 8, even 20 years of experience would not understand even your simpler snippet. These are people that have been in the industry for years, have been developing C# since 1.1 or 2.0. They are also people who still cannot reason about generics, their go-to collection of choice is still ArrayList, they can't adequately describe much less implement polymorphic behaviors, etc., I don't know what to say. Perhaps they simply haven't been pushed at their prior roles. Maybe they're not as passionate about development, or resistant to change. Maybe they're just cargo cult. Suffice it to say, I can sympathize with your plight.

1

I think you absolutely should not do this.

You are not really helping anyone, even though I understand that's what you're trying. But in the end, you are hindering understanding of the static type system by concealing something fundamental. I mean it is not like we're talking covariance/contravariance or higher order types here.
These are simple, first order type parameters with constraints. This is something every programmer should understand. If they don't then they should learn it, and they really aren't willing to, they should code in a dynamic language instead (or be fired if you ask me).

The point of static type systems is to encode your domain knowledge into language semantics. The more powerful the type system, the harder it is to learn, but the more safety you will get automatically. This is an investment of maybe half a day of tutoring at most, that will start to pay off within weeks. Your code base will become more robust, thereby more flexible and thereby the cost of responding to requirement changes and debugging in general will be cut considerably.

If you really feel you must do this, then I guess you should do something like (not sure how this should actually look in C#):

public T Generate<T>(Class<T> theClass, int paramForInstance) where T : MyClass {
    return MyClass.SomeFactoryMethod<T>(paramForInstance);
}
//which should make this possible
var instance = Generate(MyDerivedClass, 5);

The point is, that you're virtually using type parameters here. Once your co-workers accept that, transitioning to Generate<MyDerivedClass>(5) is just a small step for them, but a giant leap for your team ;)

back2dos
  • 30,140
1

One thing that I think you have to be concious of being on a development "team" is that your code needs to be readable and maintainable by others. I agree with the answers to teach and move the team forward, but until that happens you need to stick with constructs that everyone understands and is comfortable with.

bigtang
  • 2,037
0

The gerneric parameter in your code is not "dummy", since it is used as return type. This is a common pattern also used by Microsoft in the BCL. Example found in

System.Data.DataRowExtensions

public static T Field<T>(this System.Data.DataRow row, string columnName)