views:

374

answers:

5

Currently, generics in C# do not allow any sane way to perform arithmetic. There are awkward workarounds available, but none of them are very neat and all of them reduce performance. According to this interview, an interface with arithmetic types is not possible to implement, and so one such workaround is suggested.

But what you could do is have your Matrix take as an argument a Calculator, and in Calculator, have a method called multiply. You go implement that and you pass it to the Matrix.

Why should I have to tell an advanced programming language how to add and multiply numbers? [Edited due to popular demand]

Why not simply allow a Generic to be restricted to a list of types?

Eg.

class Matrix<T> where T : int,long,float,double

The syntax could of course be different. But the compiler needs only to check that the type is on the list, and that the operators used work on all types, which should be much simpler than the apparently-too-difficult interface suggestion.

Are there any obvious reasons as to why this cannot be implemented?

+2  A: 

Generics are not C++ templates. The compiler will only allow operations on generic type parameters that it can verify to be valid for those parameters, because the exact types to be used are not inserted until JIT compilation. C++ does the insertion at compile time, and doesn't care if an operation can be shown to be valid for every possible value of T, as long as it's valid for the specific value of T you're actually using.

Also, a constraint like where T : int makes no sense, because there can not be any types that derive from int, as int is a struct. The only type obeying this constraint would be int itself. If you know your type will always be int, generics become moot.

Joren
I am aware that they are not C++ templates, and that's not what I want them to be. C++ templates can easily cause runtime errors... With a list of specific types, this should not be possible, as all types can be checked at compile time.As for the second point, no sane person would indeed use "T : int". As you may note, I have listed four types, not one. The entire point would be to reduce code duplication, so I can write a single "generic" matrix rather than one for each type.
Mike K
A: 

For the very reason that clearly stated in the interview, that adding this kind of support would have added substantial additional complexity for a very minor additional benefit. If you know how to design and write compilers you could argue (in some other forum) as to what degree that is true or false, but not whether it's "stupid" or how "limited" the developers who use the language might be...

Charles Bretana
The interview referred specifically to a specific implementation other than the one I'm describing, which is WHY I described him as limited. There is ALWAYS another way to do something... how do you not see this?
Mike K
I have removed the offending section. I would hope, in future, that you could focus on the question as a whole, rather than some small subjective section.
Mike K
@Mike, You should reread the interview, in it, Anders specifically says, in his response that starts "What you are really asking is, what can you say in terms of constraints? ..." And he says, "There's a whole continuum from nothing to grand pattern matching. We think it's too little to say nothing, and the grand pattern matching becomes very complicated, so we're in- between. "
Charles Bretana
@Mike, This forum makes a definite and concerted attempt to keep the content focused on objective, technical, substantive topics, so we are perhaps a bit harsh on even minor infractions. It has the major benefit of working. No other forum I've seen has remained as professional, and absent flame-wars and subjective argumentative threads. Downside? Those with thin skins, and a tendency to violate those ideals may get a bit offended. Adapt, and you will find this forum a valuable addition to your toolkit...
Charles Bretana
+18  A: 

Why not simply allow a Generic to be restricted to a list of types?

Because then it's not generic. Generics extend the expressivity of the type system as a whole; they're not intended to be a cheap search-and-replace mechanism a la C++ templates.

Are there any obvious reasons as to why this cannot be implemented?

I deny the premise of the question. It could be implemented, if we wanted to work against the basic design principles of generics. Heck, I could implement it in less than a month, I'm quite sure, given the time and budget. However, I have other priorities.

This is incredibly stupid.

Well, when I see Anders on Monday I'll be sure to tell him that Mike K from the internet thinks that his ideas are stupid.

The fact that he even suggests this shows how limited the C# developers are.

Indeed, I am well aware of my personal limitations. I have much to learn still about programming language design and implementation.

I note also that we're also limited by our budget, and by market forces outside our control, as well as many other factors.

And finally, let me take this opportunity to point out that heaping personal insults upon the people who can answer your question works against your goal of getting your question answered. If you're interested in this topic, you might consider reading my short essay on the subject:

http://blogs.msdn.com/ericlippert/archive/2008/02/20/how-to-not-get-a-question-answered.aspx

Eric Lippert
I beg to differ. If anything, the insults only made the answer longer - by that one last paragraph.
configurator
As much as I appreciate detailed deconstructions, you will notice that I removed the "insult" more than 20 minutes before your post. Nevertheless, having to tell a compiler how to add and multiply simple numbers is indeed stupid. If a modern programming language cannot perform simple arithmetic operations, then we have taken a giant step backwards. If you disagree with that, then please, find another internet to troll.Still, "Generic" is debatable. If being applicable to any numeric type is not generic enough, then perhaps the abstraction has been taken too far.
Mike K
@Mike K: The chip on your shoulder is unbecoming. When you play an instrumental role in the design and implementation of a deeply technical tool that used and *enjoyed* by hundreds of thousands of people the world over, you'll be in a much better position to get snarky w/Eric L.
Greg D
I suspect Mike doesn't know who Eric Lippert is, or what position he holds in relation to the C# language team.
Erik Forbes
Did he just call Eric Lippert a troll??? ...wow...
Meta-Knight
Even if it was not Eric Lippert, saying something like that to someone who tries to answer your question is downright stupid -_-
Meta-Knight
The ironic thing is that I was having a conversation with Anders about exactly this topic couple days ago. The problem of genericized arithmetic is an interesting one and it's not at all clear what the best way to solve it is, or whether we ought to be spending our limited resources on solving it instead of something more important.
Eric Lippert
The irony is that I call people limited when I cannot see anything outside of my own point of view.
Mike K
RBarryYoung
Eric: "...whether we ought to be spending our limited resources on solving it instead of something more important." ME: ???!!! I guess we have widely differing views on what's "important". Making native value-types a first-class member of the .Net type and inheritance model strikes me as a pretty darn important thing.
RBarryYoung
@RBarryYoung if you write methods like follows T One(U a, V b) { return a + b; } but *manually* insert int, double, byte, long, ulong etc for T, U and V (use the same one in some cases). Once you deal with the compiler errors and warnings look at the decompiled code in reflector. Note how no function calls (the current 'building block' for most generic related behaviour) occur. Indeed note further than actually there is almost no commonality in the IL produced.Much as I would love generic arithmetic I accept that producing a eneral mechanism is *hard*.
ShuggyCoUk
F# behaves differently in this regard except you will note that it brings with it a different set of hassles (try assigning the value of an int to a float without an explicit cast for example).
ShuggyCoUk
And yet every single BASIC compiler from 1964 on has been able to correctly compile polymorphic arithmetic operators down to machine instructions without having to depend on generating function calls. I guess today's compiler technology isn't as advanced as it was in 1964? Or maybe your description is a red herring?
RBarryYoung
Native value types *are* first-class members of the .NET type system. They inherit from System.ValueType, which inherits from System.Object. Now, perhaps that inheritance hierarchy does not successfully model numbers *the way you would like*. Not much I can do about that now, unfortunately. On the fortunate side though: there is an increasingly large investment at Microsoft in understanding the needs of the scientific and financial computation community. Hopefully in the future we'll have more tools available to serve this market segment.
Eric Lippert
+1  A: 

I think you are looking for the functionality of a functional programming language in OOP. If that is the case, then use FP.

For example, in Scala, you can replace the operators, so now it can add or multiply your matrix.

This is the case in various languages, but not all OOP languages.

Why should generics be able to do addition when it isn't obvious how to add or multiply? For example, if I have a class of logarithms, then to multiply is just adding the numbers, but, how could a compiler know that?

In C# you can do operator overloading, which should solve the problem you are complaining about: http://msdn.microsoft.com/en-us/library/aa288467%28VS.71%29.aspx

The C# team came to decisions on how to do generics, and it shouldn't handle math as my example above would show, but they did allow for you to help the compiler know how to do the math operations, so blaming them for not asking them for your opinion first is very risky, as the decision has been made, generics are in as they are. It won't be changed now, I believe.

James Black
Fair enough then.
Mike K
+1  A: 

I would suggest (and excuse my limited knowledge, if this sounds retarded to anyone) to implement both template and generic functionality with their respective keywords. After reading all post (yes all of them) I have to say I agree with both views: Generics should by no means be 'be a cheap search-and-replace mechanism a la C++ templates', however when you have to implement the same function for 2+ types it becomes freaking annoying :P

Perhaps an IArithmetic interface stating the operators that need to be implemented can be used to make constrains a bit tighter?