Why does Hashtable implement both ICollection and IEnumerable? [duplicate] - c#

This question already has answers here:
Why ArrayList implement IList, ICollection, IEnumerable?
(4 answers)
Closed 8 years ago.
In .NET Framework 3.5 (C# 3.0) why does System.Hashtable implement both ICollection and IEnumerable when it already implements IDictionary that inherits these two interfaces?

Having these intefaces:
interface IFoo1 {...}
interface IFoo2: IFoo1{...}
There is no difference in terms of compilation between followings:
class MyClass: IFoo2{...}
class MyClass: IFoo2, IFoo1{...}
The second declaration makes it clearer to developers all the interfaces MyClass class implements. So it is easier to have a look at the documentation and see that MyClass implements IFoo1 interface, without digging into IFoo2 interface.

Since the direct base class of Hashtable is System.Object which implements no interfaces, interface re-implementation cannot be relevant here.
Since IDictionary does not hide any of the members it inherits from IEnumerable (for example it does not declare a new method GetEnumerator()), giving distinct implementation for members with the same names also cannot be the reason.
Since neither of the "usual" reasons applies, I have come to think that Hashtable implements both for no particular reason.
Edit:
Not sure this is even an answer.
Above statement was actually wrong. The non-generic IDictionary type does hide a member (overload) GetEnumerator() which it inherits from one of its base interface (non-generic) IEnuemrable. Not sure this is relevant, though. See the two implementations in Hashtable here and here.
New edit:
Actually, if you check the source code (found e.g. here), you see just:
public class Hashtable : IDictionary, ISerializable, IDeserializationCallback, ICloneable
But as written in an answer in a thread already linked to by a comment by Henrik, in the compiled IL, all base interfaces are still listed explicitly. Hence decompilers that go from the IL in the compiled assembly to pseudo-C#, can't tell the difference.
Final addition:
I really tried to come up with a case involving interface re-implementation where it would matter if you gave also the base interface of an already specified derived interface, but I don't think any exists. This was my try:
interface IBase
{
int Member { get; }
}
interface IDerived : IBase
{
}
class Animal : IBase
{
int IBase.Member
{
get { return 10; }
}
}
class Elephant : Animal, IDerived // try ": Animal, IBase, IDerived" ... ... ... also try ": Animal, IBase"; try ": Animal"
{
public int Member
{
get { return 20; }
}
}
static class Test
{
static void Main()
{
IBase elephantAsIBase = new Elephant();
int readMember = elephantAsIBase.Member;
Console.WriteLine(readMember);
}
}
but turned out not to be an example. Even if only IDerived is specified for Elephant, all interfaces, including IBase are re-implemented. Only if Elephant specifies neither IDerived nor IBase, is re-implementation suppressed.
So Mert's answer and the linked answer are correct, and mine is somewhat off-topic. I'll leave this post for others to learn from, even if it is not strictly relevant to the question posed.

Related

How nice to cast a class to the interface that it implements, but not at the moment of its creation [duplicate]

I know this is old, yet I am still not very good with understanding those problems. Can anyone tell me why the following does not work (throws a runtime exception about casting)?
public abstract class EntityBase { }
public class MyEntity : EntityBase { }
public abstract class RepositoryBase<T> where T : EntityBase { }
public class MyEntityRepository : RepositoryBase<MyEntity> { }
And now the casting line:
MyEntityRepository myEntityRepo = GetMyEntityRepo(); // whatever
RepositoryBase<EntityBase> baseRepo = (RepositoryBase<EntityBase>)myEntityRepo;
So, can anyone explain how is this invalid? And, I you are not in the mood to explain - is there a line of code I can use to actually do this cast?
RepositoryBase<EntityBase> is not a base class of MyEntityRepository. You're looking for generic variance which exists in C# to a limited extent, but wouldn't apply here.
Suppose your RepositoryBase<T> class had a method like this:
void Add(T entity) { ... }
Now consider:
MyEntityRepository myEntityRepo = GetMyEntityRepo(); // whatever
RepositoryBase<EntityBase> baseRepo = (RepositoryBase<EntityBase>)myEntityRepo;
baseRepo.Add(new OtherEntity(...));
Now you've added a different kind of entity to a MyEntityRepository... and that can't be right.
Basically, generic variance is only safe in certain situations. In particular generic covariance (which is what you're describing here) is only safe when you only ever get values "out" of the API; generic contravariance (which works the other way round) is only safe when you only ever put values "into" the API (e.g. a general comparison which can compare any two shapes by area can be considered as a comparison of squares).
In C# 4 this is available for generic interfaces and generic delegates, not classes - and only with reference types. See MSDN for further information, read <plug>read C# in Depth, 2nd edition, chapter 13</plug> or Eric Lippert's blog series on the topic. Also, I gave a one hour talk about this at NDC in July 2010 - the video is available here.
Whenever someone asks this question, I try to take their example and translate it to something using more well-known classes that is obviously illegal (this is what Jon Skeet has done in his answer; but I'm taking it a step further by performing this translation).
Let's replace MyEntityRepository with MyStringList, like this:
class MyStringList : List<string> { }
Now, you seem to want MyEntityRepository to be castable to RepositoryBase<EntityBase>, the reasoning being that this ought to be possible since MyEntity derives from EntityBase.
But string derives from object, doesn't it? So by this logic we should be able to cast a MyStringList to a List<object>.
Let's see what can happen if we allow that...
var strings = new MyStringList();
strings.Add("Hello");
strings.Add("Goodbye");
var objects = (List<object>)strings;
objects.Add(new Random());
foreach (string s in strings)
{
Console.WriteLine("Length of string: {0}", s.Length);
}
Uh-oh. Suddenly we're enumerating over a List<string> and we come upon a Random object. That's not good.
Hopefully this makes the issue a bit easier to understand.
This requires covariance or contravariance, whose support is limited in .Net, and cannot be used on abstract classes. You can use variance on interfaces though, so a possible solution to your problem is to create an IRepository which you use in place of the abstract class.
public interface IRepository<out T> where T : EntityBase { //or "in" depending on the items.
}
public abstract class RepositoryBase<T> : IRepository<T> where T : EntityBase {
}
public class MyEntityRepository : RepositoryBase<MyEntity> {
}
...
IRepository<EntityBase> baseRepo = (IRepository<EntityBase>)myEntityRepo;

Constrain interface implementations to structs?

An interface in C# can inherit another interface, e.g.
interface IFoo : IComparable { }
On the other hand, the following declaration is illegal:
interface IBar : struct { } // Invalid syntax
Is there any way an interface can be declared so that the implementing type is constrained to be a struct?
Is there any way an interface can be declared so that the implementing type is constrained to be a struct?
No, that is currently not possible and neither is the inverse (ensuring an interface is implemented by a class).
As far as documentation goes the closest thing I was able to find was this Interfaces, Interfaces (c#), Inheritance - Interfaces. I doubt there will be anything on an official MS site simply because (in most cases) there is no documentation on non-existing features (ignoring feature requests or features in progress) and this could be considered a non-existent feature.
Closest excerpt I could find
A class or struct can implement multiple interfaces. ...
Actually, thanks to this splendid comment by user #Evk, I realized that it is almost possible to constrain the implementation of an interface to be a struct (or analogously, a class).
The interface could be implemented as a generic interface, where the generic type parameter is constrained to be a struct that implements the interface itself:
interface IBar<T> where T : struct, IBar<T> { }
Now I can declare a struct that implements IBar:
struct BarStruct : IBar<BarStruct> { } // Works fine.
But, I cannot declare a class that implements IBar in the same way, since the generic type parameter is restricted to be a struct:
class BarClass : IBar<BarClass> { } // Will not compile!
However, it is not a waterproof approach: as user #Igor points out in the comment below, the following will still compile:
class BarClass : IBar<BarStruct> { }
You can not declare interface of struct, because classes and structs can only implement the interfaces. But you can declare interface with generic parameter as struct:
interface IBar<T> where T : struct
{
void Foo(T val); // T always be struct
}
And implement this interface:
class Bar : IBar<int>
{
public void Foo(int val) { }
}

How come an interface instance has GetType, GetHashCode, Equals and ToString methods?

Consider the following example.
public interface IAnimal
{
void MakeSound();
}
public class Dog: IAnimal
{
public void MakeSound() { Console.WriteLine("Bow-Bow-Bow"); }
public static void Main()
{
IAnimal a = new Dog();
Console.WriteLine(a.MakeSound());
Console.WriteLine(a.ToString());
}
}
How come the interface instance can access ToString method that was from System.Object? My understanding is, with interface, one can access only the methods the interface holds.
Your class implicitly derived from System.Object :
Languages typically do not require a class to declare inheritance from Object because the inheritance is implicit. [MSDN]
UPDATE :
Just found this, possible duplicate? :
Do interfaces derive from System.Object? C# spec says yes, Eric says no, reality says no
Because everything is an object. It's a cheeseball answer, but that's how .NET works. :)
My understanding is, with interface, one can access only the methods
the interface holds.
Actually, with an interface you can access the methods the interface holds and all members of System.Object (as you have discovered). This doesn't mean that interfaces themselves derives from System.Object, it just means that the compiler has a "special case" when checking for members on variables declared as interfaces.
The compiler can do this because interfaces are implemented by objects and all objects derive from System.Object.
So when a is declared as IAnimal it really means that the variable a contains an object which implement the interface IAnimal. This object is guaranteed to support all members in IAnimal and all members System.Object.

"Base abstract generic class is a bad choice in most situations." Why? (Or Why not)

I have just seen on the comment to a blog post:
Base abstract generic class is a bad
choice in most situations
Is this true, if not why?
What insight(s) leads to this statement?
I agree, because anything that inherits an abstract generic class will not be polymorphic with the base class. That is, if you have
abstract class myBase<T>
then you create
class myThing: myBase<thing>
class myOtherThing: myBase<otherThing>
you can't create methods that work against myThing and myOtherThing since they do not share an ancestor. There's no point in the base class being abstract, really, it might as well just be a class.
But if you have a base class
abstract class myBase
class myBase<T>: myBase
as is a common pattern for generic classes (like IEnumerable - using interfaces), then they all share myBase.
(edit) I just read the actual blog post - and actually, the comment is not really valid in that situation. The "abstract generic base class" he's referring to, Range<T> inherits IEnumerable<T> which inherits non-generic interface IEnumerable. So it's not really an "abstract generic base class." But generally I think it's true.
"Most situations" is outrightly vague. A generic abstract class (or interface) is a bad idea if the only common ancestor between descendants of such class is System.Object (as noted by other commenters of this question).
Otherwise (as in, if you do have a meaningful common ancestor), it's a good idea if you want to "rename" or "specialize" members. Consider this example:
// Meaningful common ancestor for the working classes.
interface IWorker
{
object DoWork();
}
// Generic abstract base class for working classes implementations.
abstract WorkerImpl<TResult> : IWorker
{
public abstract TResult DoWork();
object IWorker.DoWork()
{
return DoWork(); // calls TResult DoWork();
}
}
// Concrete working class, specialized to deal with decimals.
class ComputationWorker : WorkerImpl<decimal>
{
override decimal DoWork()
{
decimal res;
// Do lengthy stuff...
return res;
}
}
In this example, DoWork() was redefined in the abstract class, becoming concrete and specialized in ComputationWorker.
One problem with abstract generic base class is that you can't type decorate :
public abstract class Activity<TEntity>
{
public Activity() { }
protected virtual object Implementation { ... }
}
public abstract class CompensableActivity<TEntity,TCompensation> : Activity<TEntity>
where TCompensation : Activity<T>, new()
{
public CompensableActivity() { }
protected override object Implementation
{
get { new Wrapper(base.Implementation, Compensation); }
}
private Activity<TEntity> Compensation
{
get
{
var compensation = new TCompensation();
if(compensation is CompensableActivity<TEntity,Activity<TEntity>)
{
// Activity<TEntity> "does not meet new() constraint" !
var compensable = comp as CompensableActivity<TEntity, Activity<TEntity>>;
var implement = compensable.Implementation as Wrapper;
return implement.NormalActivity;
}
else { return compensation; }
}
}
}
Kragen makes a good point. Anything that is less than 50% of your code is "the wrong choice in the majority of situations".
However, even though nowhere near 50% of your classes should be generic abstract base classes, it also isn't less of a good thing than any other language feature.
For example, BindingList<T> could be considered an abstract generic base class. It's a generic container, and sorting requires you to derive from it and override ApplySortCore.
KeyedCollection<TKey, TItem> doesn't just act like an abstract generic base class, it is one. To use it you MUST derive from it and implement GetKeyForItem.
I disagree with the crowd here. In some cases an abstract generic class is the best design.
A good example in .NET can be found in System.Collections.ObjectModel where the KeyedCollection allows you to override and implement a typed serializable dictionary collection easily!
I elided most of the code but this is the principle:
public class NameCollection : System.Collections.ObjectModel.KeyedCollection<string, INamedObj>
{
protected override string GetKeyForItem(INamedObj item)
{
return item.Name;
}
}
Well, statistically speaking if someone asked me "should I make this class an abstract generic class?", the answer would almost certainly be no - in 3 years of .Net development I think I can count the number of abstract classes that I've written that had generic type parameters on one hand.
Other than that I can't see any particular reason for an abstract generic class to be considered a Bad Thing - its just not that common.
There are situations where an abstract base class is useful thing.
We have several .net applications that use different database engines. Several sql server, a couple of mysql and a bunch of oracle apps.
We have a generic common database object which is based on an abstract class that is a factory that returns the proper database object in a factory setting based on the type of database.
That way if I am starting a new application, all I have to do is load this database object, pass in the type, pass in the connection string, and bam... i'm set...
I guess what I'm trying to say is it all depends on the context and how its actually used.

C#: Abstract classes need to implement interfaces?

My test code in C#:
namespace DSnA
{
public abstract class Test : IComparable
{
}
}
Results in the following compiler error:
error CS0535: 'DSnA.Test' does not implement interface member
'System.IComparable.CompareTo(object)'
Since the class Test is an abstract class, why does the compiler require it to implement the interface? Shouldn't this requirement only be compulsory for concrete classes?
In C#, a class that implements an interface is required to define all members of that interface. In the case of an abstract class, you simply define those members with the abstract keyword:
interface IFoo
{
void Bar();
}
abstract class Foo : IFoo
{
public abstract void Bar();
}
Or to put it another way: you don't have to "implement" it (which would be a terrible limitation on abstract classes); however, in C#, you do have to tell the compiler that you are deliberately passing the buck to concrete subclasses - and the above line of code shows how to do so.
The comments and downvotes complaining that this is not an answer to the question are missing the point. Someone coming to Stack Overflow, having received this compiler error, but having an abstract class in which it would be a mistake to supply an implementation, are stuck without a good solution - would have to write implementation methods that threw runtime exceptions, a horrendous work-around - until they have the above information. Whether it is good or bad that C# requires this explicitness is outside the scope of Stack Overflow, and not relevant to the question nor this answer.
Unlike Java, in C#:
"an abstract class must provide implementations of all members of the interfaces that are listed in the base class list of the class. However, an abstract class is permitted to map interface methods onto abstract methods."
https://msdn.microsoft.com/en-us/library/Aa664595(v=VS.71).aspx
They don't have to actually implement the interface.The interface methods/properties can be abstract or even virtual as well. So its up to the subclasses to actually implement them.

Categories