Can I make a generic optional, defaulting to a certain class? - c#

My question is related to Is there a reasonable approach to "default" type parameters in C# Generics?, but using an inner generic class that approach doesn't work.
Given code like this:
using System;
public class FooEventArgs<T> : EventArgs
{
// ... T properties and a constructor
}
public class Foo<T>
{
public delegate void EventHandler<FooEventArgs>(object sender, FooEventArgs<T> e);
public event EventHandler<FooEventArgs<T>> Changed
}
And with it being used like this:
public class User
{
public Foo<int> foo1;
public Foo<object> foo2;
public User()
{
foo1 = new Foo<int>();
foo2 = new Foo<object>();
foo1.Changed += foo1_Changed;
foo2.Changed += foo2_Changed;
}
protected void foo1_Changed(object sender, FooEventArgs<int> e) { ... }
protected void foo2_Changed(object sender, FooEventArgs<object> e) { ... }
}
Well, I'd rather like it if I could have the generic optional, as there will be many cases where I don't know what type something will be coming in. (Data is coming from an external system which has its own variable types, which are then converted into .NET types, but I run into situations where, for example, one remote data type may turn into one of a couple of .NET types, or where it is of the "any" type—thus object would be the only real answer for that case.)
The solution which immediately occurred to me was subclassing (it was also the primary suggestion in the question linked to earlier):
public class Foo : Foo<object>
{
public Foo(...) : base(...) { }
}
public class FooEventArgs : FooEventArgs<object>
{
public Foo(...) : base(...) { }
}
I then want to use it like this:
public class User
{
public Foo foo3;
public User()
{
foo3 = new Foo();
foo3.Changed += foo3_Changed;
}
protected void foo3_Changed(object sender, FooEventArgs e) { ... }
}
The problem is that it naturally won't work with foo3_Changed accepting FooEventArgs; it needs FooEventArgs<object>, as that's what the Foo.Changed event will get pass to it (as the value will come from Foo<object>).
Foo.cs(3,1415926): error CS0123: No overload for 'foo3_Changed' matches delegate 'FooLibrary.Foo<object>.EventHandler<FooLibrary.FooEventArgs<object>>'
Is there anything I can do about this, short of duplicating much of the class?
I did try one other thing: an implicit operator to convert from FooEventArgs<object> to FooEventArgs.
public static implicit operator FooEventArgs(FooEventArgs<object> e)
{
return new FooEventArgs(...);
}
This, unfortunately, doesn't seem to work, though I'm not quite clear on why:
EditBuffer.cs(13,37): error CS0553: 'FooLibrary.FooEventArgs.implicit operator FooLibrary.FooEventArgs(FooLibrary.FooEventArgs<object>)': user-defined conversions to or from a base class are not allowed
So then, once again, is there anything I can do about this, or am I correct in thinking that it's Tough Luck and I'll just have to be content using FooEventArgs<object> (and then I guess I may as well just use Foo<object>)?

I don't think there's much you can do about it, to be honest. You could make Foo doubly generic:
public class Foo<TData, TArgs> where TArgs : FooEventArgs<TData>
{
public delegate void EventHandler<TArgs>(object sender, TArgs e);
public event EventHandler<TArgs> Changed;
}
Then you could write:
public class Foo : Foo<object, FooEventArgs>
... but it's really making things very complicated for very little benefit.
I would also say that even though it's a bit more verbose to include the type argument, it does make it very clear - whereas inheritance can muddy the waters in various ways. I'd steer clear of class inheritance when you're not really trying to model behaviour specialization.
The reason your implicit conversion doesn't work has nothing to do with generics, by the way - as the error message states, you can't declare a conversion (implicit or explicit) which goes up or down the inheritance hierarchy. From the C# spec section 6.4.1:
C# permits only certain user-defined conversions to be declared. In particular, it is not possible to redefine an already existing implicit or explicit conversion.
(See that section for more details.)
As a side note, I find it more common to use inheritance the other way round for generics, typically with interfaces:
public interface IFoo
{
// Members which don't depend on the type parameter
}
public interface IFoo<T> : IFoo
{
// Members which all use T
}
That way code can receive just an IFoo without worrying about the generics side of things if they don't need to know T.
Unfortunately, that doesn't help you in your specific case.

Another interesting thing I just found is that you can create generic classes with the same name but different signatures.
class Foo<T> {
}
class Foo<T,T> {
}
then you can call either one of them like follows:
new Foo<string>();
new Foo<int,double>();
new Foo<string,int>();
I just thought it was interesting that despite both classes having the same name they can co-exist because they have different signatures.
I guess this is how the Tuple class works
public class Tuple<T1, T2, T3... T8>
{
...

Related

C# Generic Method with a Parameter of that Type has no Properties on the Parameter

So, that title might be confusing, I'll try to explain. Let's say I have this code here:
public void Method<CustomClass>(CustomClass e) {
e.CustomMethod();
}
That line inside of the method, the e.GetCustomProperty(), will cause the compile to throw a temper tantrum. It seems that the class is only an object, and nothing more. I am able to do the very basics, such as e.ToString(), etc. These properties and methods are, however, present on the object, as I am able to use reflection to gain access to that method, like this:
public void Method<CustomClass>(CustomClass e) {
System.Reflection.MethodInfo method = typeof(CustomClass).GetMethod("CustomMethod");
method.Invoke(e, new object[] { });
}
The above method will compile perfectly with no issues. What exactly is the reason behind this? And is there a way around this, or will I have to use reflection?
Thank you in advance. (I have checked for about half an hour now, using specific and nonspecific search terms on Google and StackOverFlow and have not been able to find another question similar to this, so if it is a duplicate, I'll probably just cry myself to sleep).
public void Method<T>(T e) where T : CustomClass
{
e.CustomMethod();
}
This tells compiler that generic type T is CustomClass or derived from CustomClass. Therefore you'll be able to call any method without reflection. Also please check that CustomMethod's access modifier allows the call.
If you want to constrain your input type to that of a specific interface which implements a method called CustomMethod, then you can add a where statement to your method signature that indicates it.
For example, if you have this interface:
public interface ICustomInterface
{
void CustomMethod();
}
You can restrict only types that implement that interface (and therefore are guaranteed to have a CustomMethod method) by doing this (note also I changed your naming a little to indicate that CustomType is actually a generic placeholder by prefixing it with a T. Normally people just use T by itself in generics):
public void Method<TCustomClass>(TCustomClass e) where TCustomClass : ICustomInterface
{
e.CustomMethod();
}
Now if you have a class that implements the interface:
public class CustomClass : ICustomInterface
{
public void CustomMethod()
{
Console.WriteLine("Custom method called.");
}
}
You can pass it to your generic method:
private static void Main()
{
var customClass = new CustomClass();
Method(customClass);
Console.WriteLine("\nDone!\nPress any key to exit...");
Console.ReadKey();
}
Output

How does c# handle nested (generic) types?

I'm trying to understand how C# views types in the face of nesting.
More specifically I'm trying to understand why some types are not considered assignment compatible or even castable, when there "kind of" only exist one definition of the nested class. Does the compiler / CLR actually generate different types for these, or what rules are at play exactly...
Example code:
public class Foo<T>
{
protected class Private2 : Private1<Foo<T>>
{ }
protected class Private1<T2> where T2 : Foo<T>
{
public sealed class Nested
{
public void Test(T2 foo)
{
foo.Method2(this); //Nope!
var nes = (Private2.Nested)this; //Nope!
}
}
}
public void Method1()
{
var nested = new Private2.Nested();
nested.Test(this);
}
private void Method2(Private2.Nested nested)
{
// something code...
}
}
So even though the nested instance is created as a Private2.Nested it can not be casted to that type. And... well... how do the different Nested types relate to each other given that Nested is in fact sealed? (They can't be inheriting from each other right? But on the other hand their implementation should be 100% identical... am I wrong?)
Primary question: What exactly is the compiler doing when it "compiles" this nested class?? How many unique types (excluding valuetype-related) are actually generated, and if it is all the "same" type, is the restriction artificial (as in wouldn't an unsafe cast actually work)? (What I'm saying is that the IL for all these types comes from the same code definition - so at some level the compiler must know. Are instances of these types not bit-for-bit identical apart from their type-names?)
Secondary question: not what I'm really asking here, mostly for brevity / context: is there some simple change that would make the above work? Am I missing something obvious?
The type Foo<T> must never be directly referenced inside Private1<T2> - only use of T2 is allowed. Foo<T> is just my example stand in for nasty generic classes with 10~20 generic types. It's all just a "workaround" for not being able to alias a generic class with its types:
public class Bar<GoodName, OtherName, Readability, NopeMr, DontThinkSo, Suffering, Dispair>
{
//If only this was real...
using BarT = Bar<GoodName, OtherName, Readability, NopeMr, DontThinkSo, Suffering, Dispair>;
public void Method1(BarT bar) { ... } //so good!!
//goodbye readability... see you never...
public void Method2(Bar<GoodName, OtherName, Readability, NopeMr, DontThinkSo, Suffering, Dispair> whatIsThisVariable) { ... }
}
Purpose: To avoid types of fields and method-parameters that are several screens wide and utterly unreadable! >:(
...As a side note I really wished this could be used as a type inside classes and interfaces, as in Private2 : Private1<this>. Well ok, that wouldn't work because it collides with extension syntax on methods, but something similar, perhaps <this>, <super>, <base> used like Method(<this> arg) or Private2 : Private1<<super>> ... kind of weird maybe.
Consider this types:
public class Base {
public static int Value;
public class Nested { }
}
public class Derived:Base { }
What is Derived.Value and Derived.Nested. Actually, when you refer to inherited static members (nested class considered to be static member) thru derived class, you just reference base class members, so this have exactly same meaning as Base.Value and Base.Nested at compile time. There are no separate static field Derived.Value or separate class Derived.Nested.
public static void Test() {
Derived.Value=10;
Console.WriteLine(Base.Value);
Base.Value=20;
Console.WriteLine(Derived.Value);
Base.Nested bn=new Derived.Nested();
Derived.Nested dn=new Base.Nested();
Console.WriteLine(typeof(Base.Nested).FullName);
Console.WriteLine(typeof(Derived.Nested).FullName);
Console.WriteLine(typeof(Base.Nested)==typeof(Derived.Nested));
}
Original answer:
Foo<A>.Private1<B>.Nested and Foo<C>.Private1<D>.Nested considered to be different types if A!=C or B!=D. They can share same implementation internally, but for assignment compatibility they are different. Foo<T>.Private2.Nested is just alias to Foo<T>.Private1<Foo<T>>.Nested. And even if class Bar:Foo<A>{}, classes Foo<A>.Private1<Foo<A>>.Nested and Foo<A>.Private1<Bar>.Nested still considered to be different types. So Foo<T>.Private1<T2>.Nested can not be converted to Foo<T>.Private1<Foo<T>>.Nested as T2 is not necessary Foo<T>.
You're not thinking with portals. Your inner classes are already generalized on T.
public class Foo<T>
{
private class Private2 : Private1
{ }
private class Private1
{
public sealed class Nested
{
public void Test( Foo<T> foo )
{
foo.Method2( this ); //Yup
var nes = (Private2.Nested)this; //Yup
}
}
}
public void Method1()
{
var nested = new Private2.Nested();
nested.Test( this );
}
private void Method2( Private2.Nested nested )
{
// something code...
}
}
Partial answer to the primary question:
It was bugging me that you can make the code compile by changing Method2 to accept an object and cast it at runtime, because the nested instance is of the correct type (it's instantiated inside Method1). That would seem to work - as long as Foo is sealed - but as soon as someone else can subclass Private1 it is no longer guaranteed to work. (And thus not a solution.) However testing this approach reveals:
Private2.Nested is only a construct of syntax rules - using GetType() on the resulting variable says Private1.Nested and there is no Private2.Nested type.
I think the irksome feeling I was getting from this (and why I concidered sealed to be related) was some kind of confusion on my part when it came to distinguishing between subtype and inheritance. Because the outer classes are inheriting (Private1 and Private2) it feels like inheritance, and thus it feels like it should somehow be castable. But if I understand this correctly they are merely of the same subtype:
There need not be and is in fact no inheritance relation one way or the other (as the sealed clearly hints) because "the inheritance hierarchy is distinct from from the subtype hierarchy", and thus a downright conversion would be needed (since casts are bound to the inheritance hierarchy).

Exposing different interfaces from single class

We are trying to build some kind of a layer above the DAL in order to expose an interface of a certain repository methods using generics.
For example:
public interface A
{
void Do_A();
}
public interface B
{
void Do_B();
}
public void Main()
{
Exposer<A>.Do_A();
Exposer<B>.Do_B();
}
Is it possible to do that ?
Tecnically, that isn't a "single class", since Exposer<A> is a different Type to Exposer<B>; however, ultimately, this doesn't look much different to most IoC/DI containers... if this was, say, StructureMap (purely for an example), you might consider:
container.GetInstance<A>().Do_A();
container.GetInstance<B>().Do_B();
you would, of course, need to configure the container to know where the concrete A and B implementations are coming from! Which for StructureMap is shown here, but there are plenty to choose from.
If you mean directly, then: no. You cannot have:
class Exposer<T> : T {...} // non-working code to implement the interface T
You can, however, have some class:
class Exposer : A, B {...}
and just cast:
A a = Exposer;
a.Do_A();
B b = Exposer;
b.Do_B();
A type Foo<T> cannot implement (or extend) the actual T, as T is unknown at compile time. What you could do is expose a T as a property, and invoke methods on it. However, as Ondrej wrote, the question may be a little unclear.
Are you describing IoC when you write?
Exposer<A>.Do_A();
Your Exposer class makes me think to StructureMap API:
ObjectFactory.GetInstance<T>().Do_A();
If you want to get rid of the keyword new and get in a generic way an instance for a specified interface, take a look to this article or check StructureMap
To choose which interface implementation you want when consuming a given class, you don't use generics, you just cast the class to the interface:
public interface A
{
void Do_A();
}
public interface B
{
void Do_B();
}
public class Exposer : A, B
{
public void Do_A() { ; }
public void Do_B() { ; }
}
public void Main()
{
// the casts are redundant here,
// because the interface implementation
// is implicit
((A)Exposer).Do_A();
((B)Exposer).Do_B();
}
If you want to exclude members that are not implementations of members of the given interface, use explicit implementation:
public class Exposer : A, B
{
void A.Do_A() { ; }
void B.Do_B() { ; }
}
public void Main()
{
// the casts are now required;
// otherwise, you'll get a compiler error
// telling you that the method is inaccessible
((A)Exposer).Do_A();
((B)Exposer).Do_B();
}

Generics, Inheritance and the new operator

Here is something that I find myself using from time to time and I just wanted to get some feedback on the merits of the practice.
Lets say that I have a base class:
abstract class RealBase {
protected RealBase(object arg) {
Arg = arg;
}
public object Arg { get; private set; }
public abstract void DoThatThingYouDo();
}
I often create a second base class that is generic that handles the cast from the "object" type in the base class to the "T" type, like this:
abstract class GenericBase<T> : RealBase {
protected GenericBase(T arg)
: base( arg ) {
}
new public T Arg { get { return (T) base.Arg; } }
}
This allows me to access "Arg" as its explicit type without a cast operation:
class Concrete : GenericBase<string> {
public Concrete( string arg )
: base( arg ) {
}
public override void DoThatThingYouDo() {
// NOTE: Arg is type string. No cast necessary.
char[] chars = Arg.ToLowerInvariant().ToCharArray();
// Blah( blah, blah );
// [...]
}
}
All the while being able to also work with it via the "RealBase":
class Usage {
public void UseIt() {
RealBase rb = new Concrete( "The String Arg" );
DoTheThing(rb);
}
private void DoTheThing(RealBase thingDoer) {
rb.DoThatThingYouDo();
}
}
It is assumed that there are many other "Concrete" types... not just the one.
Here are my questions/concerns:
Am I "off my rocker" for using
an approach like this?
Are there
any obvious drawbacks/caveats to
using this approach?
What about
that "new public T..." in
GenericBase? Good/bad idea? Awkward?
Any feedback or advice would be greatly appreciated.
I don't have any objection to that explicitly as long as you're disciplined enough to only use the generic base class as a helper only and never downcast to it. If you start referencing RealBase and GenericBase and ConcreteClass all over the place things tend to get real tightly coupled really quickly.
As a matter of fact, I would recommend kicking it up a notch and introducing an interface
interface IReal {
void DoThatThingYouDo();
}
And leaving the base class out of it entirely (basically never reference it except when declaring a derived class). Just a tip that helps me increase the flexibility of my code.
Oh, and if you do use an interface, don't just declare it in the base classes, declare it on the concrete ones:
class MyConcrete: BaseClass<MyConcrete>, IReal {
...
}
as a reminder, the base class is not important only what it does is important!
Well, we've now got an inheritance tree three levels deep, but you haven't given any particular reason for doing this.
Personally I rarely use inheritance (or rather, rarely design my own inheritance hierarchies beyond implementing interfaces and deriving directly from object). Inheritance is a powerful tool, but one which is difficult to use effectively.
If this gives you some clear advantage over other approaches, that's fine - but I would consider the complexity you're adding for someone reading the code. Do they really want to have to consider three levels of hierarchy, with two properties of the same name? (I would rename GenericBase.Arg to GenericBase.GenericArg or something like that.)
I think you would be able to get the same functionality you would like by using an interface as opposed to dual abstract base classes, consider this:
public interface IAmReal
{
void DoThatThingYouDo();
...
}
abstract class GenericBase<T> : IAmReal
{
protected GenericBase<T>(T arg)
{
Arg = arg;
}
public T Arg { get; set; }
public abstract void DoThatThingYouDo();
}
class MyConcrete : GenericBase<string>
{
public MyConcrete(string s) : base(s) {}
public override void DoThatThingYouDo()
{
char[] chars = Arg.ToLowerInvariant().ToCharArray();
...
}
}
class Usage
{
public void UseIt()
{
IAmReal rb = new MyConcrete( "The String Arg" );
DoTheThing(rb);
}
private void DoTheThing(IAmReal thingDoer)
{
rb.DoThatThingYouDo();
}
}
I don't think you're off your rocker. See Curiously Recurring Template for something even more complex.
Personally I would strongly advise not to use the new operator, since it may lead to confusion. Actually I myself have recently had such a problem, but I went with base class abstract suffixed with AsObject, i.e.:
public BaseClass{
public abstract object ValueAsObject {get;set;}
}
and generic class along the line:
public BaseClass<T> : BaseClass {
public T Value {get;set;}
public override object ValueAsObject {
get{return (T)this.Value;}
set{this.Value = value;} // or conversion, e.g. string -> int
}
Georg Mauer's proposal of interface for DoThatThingYouDo is also good.
Am I the only one who thinks inheritance should be avoided as far as it can? I've seen different implementations when inheritance have caused bizarre problems, not only when trying to downcast. Interfaces are the savior! I'm not saying that inheritance should always be avoided, but by just looking at the specified code I can't see the advantages of this inheritance tree over regular interfaces.

Why cast to an interface?

In Jesse Liberty's Programming C# (p.142) he provides an example where he casts an object to an interface.
interface IStorable
{
...
}
public class Document : IStorable
{
...
}
...
IStorable isDoc = (IStorable) doc;
...
What is the point of this, particularly if the object's class implements the inteface anyway?
EDIT1: To clarify, I'm interested in the reason for the cast (if any), not the reason for implementing interfaces. Also, the book is his 2001 First Edition (based on C#1 so the example may not be germane for later versions of C#).
EDIT2: I added some context to the code
Because you want to restrict yourself to only methods provided by the interface. If you use the class, you run the risk of calling a method (inadvertently) that's not part of the interface.
There is only one reason when you actually need a cast: When doc is of a base type of an actual object that implements IStorable. Let me explain:
public class DocBase
{
public virtual void DoSomething()
{
}
}
public class Document : DocBase, IStorable
{
public override void DoSomething()
{
// Some implementation
base.DoSomething();
}
#region IStorable Members
public void Store()
{
// Implement this one aswell..
throw new NotImplementedException();
}
#endregion
}
public class Program
{
static void Main()
{
DocBase doc = new Document();
// Now you will need a cast to reach IStorable members
IStorable storable = (IStorable)doc;
}
}
public interface IStorable
{
void Store();
}
If the object implements the interface explicitly (public void IStorable.StoreThis(...)) that casting is the easiest way to actually reach the interface members.
I am not sure under what context the example was given in the book. But, you generally can type cast an object to interface to achieve multiple inheritance. I have given the example below.
public interface IFoo
{
void Display();
}
public interface IBar
{
void Display();
}
public class MyClass : IFoo, IBar
{
void IBar.Display()
{
Console.WriteLine("IBar implementation");
}
void IFoo.Display()
{
Console.WriteLine("IFoo implementation");
}
}
public static void Main()
{
MyClass c = new MyClass();
IBar b = c as IBar;
IFoo f = c as IFoo;
b.Display();
f.Display();
Console.ReadLine();
}
This would display
IBar implementation
IFoo implementation
It's pretty hard to tell without more of the context. If the variable doc is declared to be a type which implements the interface, then the cast is redundant.
Which version of the book are you reading? If it's "Programming C# 3.0" I'll have a look tonight when I'm at home.
EDIT: As we've seen in the answers so far, there are three potential questions here:
Why cast in the statement shown in the question? (Answer: you don't have to if doc is of an appropriate compile-time type)
Why is it ever appropriate to explicitly cast to an implemented interface or base class? (Answer: explicit interface implementation as shown in another answer, and also for the sake of picking a less specific overload when passing the cast value as an argument.)
Why use the interface at all? (Answer: working with the interface type means you're less susceptible to changes in the concrete type later on.)
The doc object might be of a type that implements members of IStorable explicitly, not adding them to the classes primary interface (i.e., they can only be called via the interface).
Actually "casting" (using the (T) syntax) does not make any sense since C# handles upcasts (cast to parent type) automatically (unlike F# for instance).
There are a lot of good answers here, but I don't really think they answer WHY you actually WANT to use the most restrictive interface possible.
The reasons do not involve your initial coding, they involve the next time you visit or refactor the code--or when someone else does it.
Let's say you want a button and are placing it on your screen. You are getting the button either passed in or from another function, like this:
Button x=otherObject.getVisibleThingy();
frame.add(x);
You happen to know that VisibleThingy is a button, it returns a button, so everything is cool here (no cast required).
Now, lets say that you refactor VisibleThingy to return a toggle button instead. You now have to refactor your method because you knew too much about the implementation.
Since you only NEED the methods in Component (a parent of both button and Toggle, which could have been an interface--same thing pretty much for our purposes), if you had written that first line like this:
Component x=(Component)otherObject.getVisibleThingy();
You wouldn't have had to refactor anything--it would have just worked.
This is a very simple case, but it can be much more complex.
So I guess the summary would be that an interface is a specific way to "View" your object--like looking at it through a filter...you can only see some parts. If you can restrict your view enough, the object can "Morph" behind your particular view and not effect anything in your current world--a very powerful trick of abstraction.
The best reason why you would cast to interfaces would be if you are writing code against objects and you don't know what concrete type they are and you don't want to.
If you know that you might come across an object that implements a specific interface you could then get the values out of the object without having to know the concrete class that this object is. Also, if you know that an object implements a given interface, that interface might define methods that you can execute to take certain actions on the object.
Here's a simple example:
public interface IText
{
string Text { get; }
}
public interface ISuperDooper
{
string WhyAmISuperDooper { get; }
}
public class Control
{
public int ID { get; set; }
}
public class TextControl : Control, IText
{
public string Text { get; set; }
}
public class AnotherTextControl : Control, IText
{
public string Text { get; set; }
}
public class SuperDooperControl : Control, ISuperDooper
{
public string WhyAmISuperDooper { get; set; }
}
public class TestProgram
{
static void Main(string[] args)
{
List<Control> controls = new List<Control>
{
new TextControl
{
ID = 1,
Text = "I'm a text control"
},
new AnotherTextControl
{
ID = 2,
Text = "I'm another text control"
},
new SuperDooperControl
{
ID = 3,
WhyAmISuperDooper = "Just Because"
}
};
DoSomething(controls);
}
static void DoSomething(List<Control> controls)
{
foreach(Control control in controls)
{
// write out the ID of the control
Console.WriteLine("ID: {0}", control.ID);
// if this control is a Text control, get the text value from it.
if (control is IText)
Console.WriteLine("Text: {0}", ((IText)control).Text);
// if this control is a SuperDooperControl control, get why
if (control is ISuperDooper)
Console.WriteLine("Text: {0}",
((ISuperDooper)control).WhyAmISuperDooper);
}
}
}
running this little program would give you the following output:
ID: 1
Text: I'm a text control
ID: 2
Text: I'm another text control
ID: 3
Text: Just Because
Notice that I didn't have to write any code in the DoSomething method that required me to know anything about all the objects I was working on being concrete object types. The only thing that I know is that I'm working on objects that are at least an instance of the Control class. I can then use the interface to find out what else they might have.
There's a million different reasons that you would take this approach with interfaces on your objects but it gives you a loose way to access your objects without having to know exactly what it is.
Think of all the credit cards in the world, every company makes their own, the interface is the same though, so every card reader can have a card swiped through it that follows the standard. Similar to the usage of interfaces.
As has been noted, the casting is superfluous and not necessary. However, it is a more explicit form of coding which would be useful to beginners in aiding their understanding.
In an introductory textbook, it is best to explicitly act, rather than let the compliler do things implicitly, which would be more confusing for beginners.
The "doc" is not of type "IStorable" so it would be confusing for beginners to see that it is being assigned to a isDoc. By explicitly casting, the author (of the book and of the code) is saying that a document can be casted to an IStorable object, but it is NOT THE SAME as an IStorable object.
The point is, the object (where did you get it?) may not implement the interface, in which case an exception is thrown which can be caught and dealt with. Of course you can use the "is" operator to check, and the "as" operator to cast instead of the C-style cast.
To allow for the most decoupling between pieces of code...
See the following article for more:
Interfaces
The main reason you would explicitly cast to an interface is if the members of the interface are implemented explicitly (i.e. with fully-qualified names in the form of InterfaceName.InterfaceMemberName). This is because when you fully-qualify them with the interface name, those members are not actually part of the implementing class's API. You can only get to them via casting to the interface.
Here's an example you can run as-is:
using System;
public interface ISomethingDoer {
void DoSomething();
}
public class ThingA : ISomethingDoer {
public void DoSomething(){
Console.WriteLine("ThingA did it!");
}
}
public class ThingB : ISomethingDoer {
// This is implemented explicitly by fully-qualifying it with the interface name
// Note no 'scope' here (e.g. public, etc.)
void ISomethingDoer.DoSomething(){
Console.WriteLine("ThingB did it!");
}
}
public static class Runner {
public static void Main(){
var a = new ThingA();
a.DoSomething(); // Prints 'ThingA did it!'
var b = new ThingB();
b.DoSomething(); // NOTE: THIS WILL NOT COMPILE!!!
var bSomethingDoer = (ISomethingDoer)b;
bSomethingDoer.DoSomething(); // Prints 'ThingB did it!'
}
}
HTH!

Categories

Resources