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?"

10
  • 1
    Seriously, this is not the type of code a a manager is supposed to comprehend, and accordingly, should not critique!
    – NoChance
    Dec 18, 2011 at 8:54
  • @EmmadKareem He's a developer with some management responsibility.
    – sq33G
    Dec 18, 2011 at 8:56
  • is the downvoter suggesting that I should drop generics altogether, or that I should drop job security altogether? ;)
    – sq33G
    Dec 18, 2011 at 10:04
  • thanks for the reply. I did not downvote.
    – NoChance
    Dec 18, 2011 at 10:14
  • 8
    I'm sorry to say this, but someone who says something like your managed and colleagues said is senior in age only. :p A senior dev should 1) probably already know about this and 2) relish the opportunity to learn it otherwise...
    – Max
    Dec 18, 2011 at 10:44

7 Answers 7

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).

7
  • I actually do tutorials whenever there's downtime (outages, breaks, whatever) - but management and the senior team do not attend. To be fair, they're in a different location.
    – sq33G
    Dec 18, 2011 at 9:56
  • 1
    @sq33G - Anyone who develops should at least be invited. If the developer (?) who freaked out on you is developing, he should be interested in attending. If he isn't, he has no business looking at code.
    – Oded
    Dec 18, 2011 at 9:58
  • 1
    +1: Totally agree. Time to move on. Working for such luddites will likely limit your appeal to future employers.
    – Jim G.
    Dec 18, 2011 at 10:03
  • 4
    +1: I fail to see the difference between "don't use generics," "don't use a ternary operator," and "don't use the not (!) operator." They're all fundamental parts of the toolkit.
    – pdr
    Dec 18, 2011 at 10:22
  • 1
    @pdr - It's the good old "we don't use what we don't understand". I have had the same experience a few years ago when asking why interfaces were not being used.
    – Oded
    Dec 18, 2011 at 10:24
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.

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.

2
  • 1
    Actually, I was asking "How nonstandard is this, and how likely is it to teach bad habits to people not yet familiar with generics?"
    – sq33G
    Dec 18, 2011 at 17:53
  • 3
    @sq33G, fair enough, I misunderstood slightly. In that case the answers are "It's non-standard enough that if I saw it in a code review I'd assume you didn't know generics properly"; and "Very likely". Dec 18, 2011 at 23:47
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 ;)

5
  • Let's not be too generous here. I'm not trying to help anyone, I'm trying to write code that makes sense. In order to do this without freaking people out, I'd like to make it possible to use my code as widely as possible throughout the code base without forcing callers to include type parameters in their call. In any case - I'm not sure what you're trying to say with your example that I haven't already said with mine. Am I missing something?
    – sq33G
    Dec 19, 2011 at 12:58
  • @sq33G: Firstly, I said you shouldn't do it. Secondly, I said if you must then I would do it the way I proposed, because it is more explicit (you don't pass a typed null value to transport the type, but a physical type value instead), more concise and very close to actually including type parameters.
    – back2dos
    Dec 19, 2011 at 13:24
  • Can you provide documentation for Class<T>? You seem to be using it like Type, but a Type that magically knows what to do with a type.
    – sq33G
    Dec 19, 2011 at 13:34
  • 1
    @sq33G: Sorry, I can't. I was expecting C# to have something like this, since even Java has it. But upon further investigation, I surprisingly found no such thing, and if Type is the type of class objects in C#, then what I proposed is impossible.
    – back2dos
    Dec 19, 2011 at 14:23
  • I believe that even in Java, that would have to be MyDerivedClass.class. In C# there is only the semi-equivalent typeof(MyDerivedClass), but it happens not to provide the type parameter where Java does.
    – sq33G
    Dec 20, 2011 at 7:22
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.

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)
5
  • Is this meant to be a case in point?
    – sq33G
    Dec 18, 2011 at 17:36
  • @sq33G: It is the case which first came into my mind. I am sure you will find better examples. Dec 18, 2011 at 17:57
  • I think you only read the first part of my code block, which was a counterexample. The example is right after that.
    – sq33G
    Dec 18, 2011 at 18:29
  • 1
    Sorry, I thought it you were talking about a generic type parameter, but you are talking about a generic method parameter. Nevertheless, you should not use a programmatic workaround for human ignorance. Instead, send your senior programmers an email with this link: where generic type constraint Dec 18, 2011 at 19:34
  • where was two+ weeks ago. This week I'm just trying to add a generic method or two to the codebase without bringing about a new wave of obviously generic method calls.
    – sq33G
    Dec 18, 2011 at 19:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.