C# improvements
-
There is an interesting MSDN article about the planned additions to C#. However, this looks strange to me:
public class Dictionary<KeyType, ValType> where KeyType : IComparable
{
public void Add(KeyType key, ValType val)
{
...
switch(key.CompareTo(x))
{
}
...
}
}Some kind of specialization? :~
Which part are you talking about? The generics or the switch statement?
any idiot can write haiku you just stop at seventeenth syl -ThinkGeek Fortunes
-
There is an interesting MSDN article about the planned additions to C#. However, this looks strange to me:
public class Dictionary<KeyType, ValType> where KeyType : IComparable
{
public void Add(KeyType key, ValType val)
{
...
switch(key.CompareTo(x))
{
}
...
}
}Some kind of specialization? :~
Well, this could be in the C# forum, but let's go: This is done to give more decent compilation error messages when using templates than in C++ (if you used STL, you know what I mean). Actually, when you use a class as a template parameter, this class must "implement a interface", but in C++ you do not declare this interface formally. In C#, it will be this way.
It's not the fall that kills you: it's the sudden stop - Down by Law, Jim Jamursch (1986)
-
There is an interesting MSDN article about the planned additions to C#. However, this looks strange to me:
public class Dictionary<KeyType, ValType> where KeyType : IComparable
{
public void Add(KeyType key, ValType val)
{
...
switch(key.CompareTo(x))
{
}
...
}
}Some kind of specialization? :~
Nemanja Trifunovic wrote: Some kind of specialization? Not precisely. It's a constraint. It says that Dictionary<> can be instantiated only with a KeyType type that has implemented IComparable. If Foo doesn't implment IComparable then instantiating Dictionary is a compile time error. This allows static verification that a type provides the needed interfaces/operations for instantiation. Specializations, on the other hand, are used to change the implementation based on the templated type. Different beasts. In C++ you can compare the C# constraint to the less strict/more flexible concept checking idioms (http://www.boost.org/libs/concept_check/concept_check.htm[^]). There's been talk of adding constraints to C++ as well, but something more along the lines of concept checking (where you don't have to inherit any base classes or implement any interfaces, assuming C++ had such a thing, you only have to provide the appropriate operations). But I'm not aware of any such proposals currently submitted. William E. Kempf
-
Which part are you talking about? The generics or the switch statement?
any idiot can write haiku you just stop at seventeenth syl -ThinkGeek Fortunes
I'm talking about
where KeyType : IComparable
part -
Nemanja Trifunovic wrote: Some kind of specialization? Not precisely. It's a constraint. It says that Dictionary<> can be instantiated only with a KeyType type that has implemented IComparable. If Foo doesn't implment IComparable then instantiating Dictionary is a compile time error. This allows static verification that a type provides the needed interfaces/operations for instantiation. Specializations, on the other hand, are used to change the implementation based on the templated type. Different beasts. In C++ you can compare the C# constraint to the less strict/more flexible concept checking idioms (http://www.boost.org/libs/concept_check/concept_check.htm[^]). There's been talk of adding constraints to C++ as well, but something more along the lines of concept checking (where you don't have to inherit any base classes or implement any interfaces, assuming C++ had such a thing, you only have to provide the appropriate operations). But I'm not aware of any such proposals currently submitted. William E. Kempf
William E. Kempf wrote: It says that Dictionary<> can be instantiated only with a KeyType type that has implemented IComparable. Than why KeyType as a generics parameter? We could use IComparable directly, couldn't we?
public void Add(IComparable key, ValType val)
{
...
switch(key.CompareTo(x))
{
}
...
} -
I'm talking about
where KeyType : IComparable
partAh...I see. In that case, Daniel's response it what you want to read. It's a way for the compiler to check if KeyType implements IComparable, because otherwise the key.CompareTo() method is totally invalid.
any idiot can write haiku you just stop at seventeenth syl -ThinkGeek Fortunes
-
William E. Kempf wrote: It says that Dictionary<> can be instantiated only with a KeyType type that has implemented IComparable. Than why KeyType as a generics parameter? We could use IComparable directly, couldn't we?
public void Add(IComparable key, ValType val)
{
...
switch(key.CompareTo(x))
{
}
...
}No, because CompareTo() is part of the IComparable interface...there's no garuntee that the object will have a CompareTo() member without declaring that it must implement IComparable.
any idiot can write haiku you just stop at seventeenth syl -ThinkGeek Fortunes
-
Well, this could be in the C# forum, but let's go: This is done to give more decent compilation error messages when using templates than in C++ (if you used STL, you know what I mean). Actually, when you use a class as a template parameter, this class must "implement a interface", but in C++ you do not declare this interface formally. In C#, it will be this way.
It's not the fall that kills you: it's the sudden stop - Down by Law, Jim Jamursch (1986)
I see. However, it looks strange to me. I always thought of interfaces as a mean of dynamic polymorfism (with virtual functions), and now they are using them for static polymorphism (generics). I would rather keep these concepts separated.
-
No, because CompareTo() is part of the IComparable interface...there's no garuntee that the object will have a CompareTo() member without declaring that it must implement IComparable.
any idiot can write haiku you just stop at seventeenth syl -ThinkGeek Fortunes
I don't think you read my post carefuly. If you declare something as IComparable directly (forget about generics for a second) then it must have CompareTo member. My question is: what are the benefits of generics + constraints vs passing an interface old way. If it was C++, I would think about optimization being a reason.
-
William E. Kempf wrote: It says that Dictionary<> can be instantiated only with a KeyType type that has implemented IComparable. Than why KeyType as a generics parameter? We could use IComparable directly, couldn't we?
public void Add(IComparable key, ValType val)
{
...
switch(key.CompareTo(x))
{
}
...
}This is not generic, and forces the use of casts, as is the case today. With your signature, I could Add() ANY key to Dictionary, so long as it implemented IComparable. However, given what the article had:
public class Dictionary<KeyType, ValType> where KeyType : IComparable
{
public void Add(KeyType key, ValType val)
{
...
switch(key.CompareTo(x))
{
}
...
}
}and an instantiation of Dictionary<Foo, Bar>, then you can only pass in Foo instances to Add(). So you get strong type checking, but because of the generic usage, I can instantiate multiple types of Dictionary: Dictionary<Foo, Bar>, Dictionary<Bar, Foo>, Dictionary<Duck, Quack>, etc, as long as the KeyType meets the constraint (i.e. implements the interface IComparable). I'm not sure that I care for the fact that you HAVE to constrain a type or cast it in the code in order to use members not part of the base object type, coming from a C++ background, but it does lend to easier implementation of strongly typed generics, which means better compiler diagnostics. William E. Kempf
-
I don't think you read my post carefuly. If you declare something as IComparable directly (forget about generics for a second) then it must have CompareTo member. My question is: what are the benefits of generics + constraints vs passing an interface old way. If it was C++, I would think about optimization being a reason.
Nemanja Trifunovic wrote: My question is: what are the benefits of generics + constraints vs passing an interface old way. If it was C++, I would think about optimization being a reason. Mostly code reuse. However, you can also get some optimizations here as well. The constraint is checked at compile time, so the compiler can perform more efficient forms of casting since it won't have to make a runtime check that the object is of the appropriate type. William E. Kempf
-
This is not generic, and forces the use of casts, as is the case today. With your signature, I could Add() ANY key to Dictionary, so long as it implemented IComparable. However, given what the article had:
public class Dictionary<KeyType, ValType> where KeyType : IComparable
{
public void Add(KeyType key, ValType val)
{
...
switch(key.CompareTo(x))
{
}
...
}
}and an instantiation of Dictionary<Foo, Bar>, then you can only pass in Foo instances to Add(). So you get strong type checking, but because of the generic usage, I can instantiate multiple types of Dictionary: Dictionary<Foo, Bar>, Dictionary<Bar, Foo>, Dictionary<Duck, Quack>, etc, as long as the KeyType meets the constraint (i.e. implements the interface IComparable). I'm not sure that I care for the fact that you HAVE to constrain a type or cast it in the code in order to use members not part of the base object type, coming from a C++ background, but it does lend to easier implementation of strongly typed generics, which means better compiler diagnostics. William E. Kempf
William E. Kempf wrote: This is not generic, and forces the use of casts, as is the case today. With your signature, I could Add() ANY key to Dictionary That answers my question. Thanks.
-
I see. However, it looks strange to me. I always thought of interfaces as a mean of dynamic polymorfism (with virtual functions), and now they are using them for static polymorphism (generics). I would rather keep these concepts separated.
Nemanja Trifunovic wrote: I always thought of interfaces as a mean of dynamic polymorfism (with virtual functions), and now they are using them for static polymorphism (generics). I think they're ok because it's only to tell the compiler that an interface must be supported in order to instanciate the template. This avoids runtime errors and in this case, it is a good thing.
There are only 10 kind of people in the world: those who understand binary and those who don't.