I'm trying to create instance of class Bar but I'm receiving an error:
"Cannot implicitly convert type ConsoleApplication1.Bar to
ConsoleApplication1.BaseFoo<ConsoleApplication1.baseOutput,
ConsoleApplication1.baseInput>"
Any idea what I'm missing or what I'm doing wrong? Any advice will be nice.
public class baseOutput
{
public string output;
}
public class baseInput
{
public string input;
}
public class ExtendOutput : baseOutput
{
public long id;
}
public class ExtendInput : baseInput
{
public long id;
}
public class BaseFoo<baseOutput, baseInput>
{
protected virtual void DoSmth()
{
}
}
public class Bar : BaseFoo<ExtendOutput, ExtendInput>
{
protected override void DoSmth()
{
base.DoSmth();
}
}
public class Test
{
public void Show()
{
}
private BaseFoo<baseOutput, baseInput> CreateInstance()
{
return new Bar(); // Error right here
}
}
I'll give you an example of why you're prevented from doing that.
Imagine instead, your classes were written like this:
public class BaseFoo<TOutput, TInput>
where TOutput : BaseOutput
{
public TOutput Something { get; set; }
}
public class Bar : BaseFoo<ExtendOutput, ExtendInput>
{
}
public class BaseInput { }
public class BaseOutput { }
public class ExtendOutput : BaseOutput { }
public class SomethingElse : BaseOutput { }
Now, you have this method:
private BaseFoo<BaseOutput, BaseInput> CreateInstance()
{
//At this point, Something will be of type ExtendOutput.
return new Bar();
}
So, we call it like this:
var myBar = CreateInstance();
Now, mybar.Something is of type BaseOutput. That's fine, though, because ExtendOutput : BaseOutput, right? Not quite.
What happens when we do this:
myBar.Something = new SomethingElse();
That's valid, because Something expects a BaseOutput, and SomethingElse is a BaseOutput. However, the object is actually a Bar, which explicitly says it should be an ExtendOutput.
The problem is clearer if we attempt to cast it back:
var myBaseFoo = CreateInstance();
myBaseFoo.Something = new SomethingElse();
Bar myBar = (Bar)myBaseFoo;
myBar.Something; // Here, we're told it's going to be an `ExtendOutput`,
// but we get a `SomethingElse`?
That's clearly wrong. And that's why you're prevented from doing what you're trying to do. You can have this behavior with covariance.
Covariance makes it illegal to pass in a TOutput. So, this line
public TOutput Something { get; set; }
Would be invalid. We would only be allowed to expose the getter:
public TOutput Something { get; }
Which alleviates the above problem
Bar is BaseFoo<ExtendOutput, ExtendInput>, and CreateInstance() requires BaseFoo<baseOutput, baseInput> to be returned, so it can't return Bar which is BaseFoo<ExtendOutput, ExtendInput>.
Regardless ExtendOutput inherits baseOutput, when you inherit a generic class the inheritance is invariant.
Consider using interfaces with in and out generic modifiers:
public class baseOutput
{
public string output;
}
public class baseInput
{
public string input;
}
public class ExtendOutput : baseOutput
{
public long id;
}
public class ExtendInput : baseInput
{
public long id;
}
public interface IBaseFoo<out T1, out T2>
{
public void DoSmth();
}
public class Bar : IBaseFoo<ExtendOutput, ExtendInput>
{
public void DoSmth()
{
}
}
public class Test
{
public void Show()
{
}
private IBaseFoo<baseOutput, baseInput> CreateInstance()
{
return new Bar();
}
}
Related
I need to create a dll file which contains all the interfaces of the classes but doesn't contain any class.
Because I use these interfaces for a lot of classes it's must be like that:
public interface IClassA
{
string Word { get; }
}
public interface ITest<TClassA> where TClassA : IClassA
{
TClassA A { get; }
}
Example of two classes that implements these interfaces the way I want:
public class ClassA : IClassA
{
public string Word
{
get;
private set;
}
public string Sentence
{
get;
private set;
}
public ClassA(string word, string sentence)
{
this.Word = word;
this.Sentence = sentence;
}
}
public class Test : ITest<ClassA>
{
public ClassA A
{
get;
private set;
}
public Test(ClassA a)
{
this.A = a;
}
}
And I want to do something like that in the main program:
public static void Main(string[] args)
{
ClassA a = new ClassA("hey", "hey world!");
Test t = new Test(a);
Print((ITest<IClassA>)t);
}
public static void Print(ITest<IClassA> t)
{
Console.WriteLine(t.A.Word);
}
But this casting: (ITest<IClassA>)t makes a run time error.
How can I solve it?
thanks!
You should declare Test as
public class Test : ITest<IClassA>
instead of ITest<ClassA>.
Or declare ITest<TClassA> to be covariant on TClassA:
public interface ITest<out TClassA> where TClassA : IClassA
The Test-class implements the concrete ClassA (public class Test : ITest<ClassA>).
So you're trying to cast an ITest<ClassA> to ITest<IClassA> which obviously fails.
If you let the Test-class implement IClassA, the cast works:
public class Test : ITest<IClassA>
{
public IClassA A
{
get; private set;
}
public Test(IClassA a)
{
this.A = a;
}
}
How do I define a factory whose implementations may accept different numbers of parameters?
public abstract class CarFactory
{
public abstract void countStuff(??); //not sure how to define this
}
I would like the factory to be able to create different objects like:
public class BMW : CarFactory
{
public override void countStuff(param1, param2) {}
}
public class Ford : CarFactory
{
public override void countStuff(param1) {}
}
Not sure if "countStuff" should be a factory responsibility, but you could get something similar this way:
public interface ICountParam {}
public class BmwParam : ICountParam
{
public BmwParam(string a)
{
A = a;
}
public string A { get; set; }
}
public class FordParam : ICountParam
{
public FordParam(string a, string b)
{
A = a;
B = b;
}
public string A { get; set; }
public string B { get; set; }
}
public interface ICarFactory<in T> where T : ICountParam
{
void CountStuff(T param);
}
public class BMW : ICarFactory<BmwParam>
{
public void CountStuff(BmwParam param) { }
}
public class Ford : ICarFactory<FordParam>
{
public void CountStuff(FordParam param) { }
}
Usage:
bmw.CountStuff(new BmwParam("A"));
ford.CountStuff(new FordParam("A", "B"));
A noob question...
I've got two classes, a common(parent) one and a specialized(child)one :
public abstract class BaseTest
{
public BaseTestSettings Settings{get;set;}
public abstract void Run();
}
public class BaseTestSettings
{
public double SettingsProp1{get;set;}
public double SettingsProp1{get;set;}
}
public class SpecializaedTestSettings : BaseTestSettings
{
public double SpecializaedTestSettingsPropA{get;set;}
public double SpecializaedTestSettingsPropB{get;set;}
}
public class SpecializaedTest : BaseTest
{
public SpecializaedTest()
{
this.Settings = new SpecializaedTestSettings();
}
public override void Run()
{
SpecializaedTestSettings settings = (SpecializaedTestSettings)this.Settings;
}
}
Is there a way to avoid casting in the overridden Run method in the specialized test ? I guess a solution would be to define a Settings property of type SpecializedTestSettings in the SpecializedTest class, but my goal is to avoid to this and declare those properties only once. I guess I can't ?
Use Generics :
public abstract class BaseTest<TSettings> where TSettings : BaseTestSettings
{
public TSettings Settings{get;set;}
public abstract void Run();
}
public class BaseTestSettings
{
public double SettingsProp1{get;set;}
public double SettingsProp1{get;set;}
}
public class SpecializaedTestSettings : BaseTestSettings
{
public double SpecializaedTestSettingsPropA{get;set;}
public double SpecializaedTestSettingsPropB{get;set;}
}
public class SpecializaedTest : BaseTest<SpecializaedTestSettings>
{
public SpecializaedTest()
{
this.Settings = new SpecializaedTestSettings();
}
public override void Run()
{
SpecializaedTestSettings settings = this.Settings;
}
}
If you need a non generic/covariant version you can write a covariant interface or a non generic base type.
I am attempting to do something similar to:
public interface IView<T> : T where T : class
{
T SomeParam {get;}
}
So that i can later do
public class SomeView : IView<ISomeView>
{
}
Is it possible to specify inheritance using generics in this way or do i have to go the long way round and explicitly specify both interfaces when defining the class and do:
public interface IView<T>
{
T SomeParam {get;}
}
public class SomeView : IView<ISomeView>, ISomeView
{
}
This isn't possible, but your goal may be achievable with conversion operators. It seems that what you're trying to do is make it possible to pass an IView<T> as the T object which it contains. You could write a base class like this:
public abstract class ViewBase<T> {
public abstract T SomeParam { get; }
public static implicit operator T(ViewBase<T> view) {
return view.SomeParam;
}
}
Then, if you define a class like:
public class SomeView : ViewBase<ISomeView> { }
It can be accepted anywhere an ISomeView is expected:
ISomeView view = new SomeView();
Short answer: It is not possible. See this post
An Interface can't derive from a class. However nothing prevent you from doing this:
public interface ISomeView
{
}
public interface IView<out T> where T:class
{
T SomeParam { get; }
}
public class SomeView:IView<ISomeView>
{
public ISomeView SomeParam { get; set; }
}
Edit:
If you don't want to implement the T SomeParam { get; } each time you need to have an implementation, Does this would work?
public interface ISomeView
{
}
public abstract class BaseView<T> where T : class
{
public T SomeParam { get; set; }
}
public class SomeView : BaseView<ISomeView>{
}
In both case this would work:
public class main
{
public class OneOfThoseView : ISomeView
{
}
public main()
{
OneOfThoseView oneOfThose = new OneOfThoseView();
SomeView x = new SomeView();
x.SomeParam = oneOfThose;
}
}
Edit 2:
Not exactly what you want to do but this would force your SomeView class to return a BaseView<SomeView> class
public interface ISomeView
{
}
public abstract class BaseView<T> where T : BaseView<T>
{
public T SomeParam { get; set; }
}
public class SomeView : BaseView<SomeView>
{
}
Now only this would work.
public main()
{
SomeView y= new SomeView ();
SomeView x = new SomeView();
x.SomeParam = y;
}
I trying to figure out how to write a class where the base class would supply the accessor functions and then the instanced class only needs to supply the values.
Something like this:
public interface IBaseClass
{
int GetHandlerID();
}
public abstract class AbstractClass : IBaseClass
{
private int HandlerID;
public virtual int GetHandlerID()
{
return (this.HandlerID);
}
}
public class MyClass : AbstractClass
{
int HandlerID = 1;
}
class Program
{
static void Main(string[] args)
{
MyClass newClass = new MyClass();
Console.WriteLine("HandlerID: {0}"), newClass.GetHandlerID() );
}
}
It doesn't work this way because the class is going to read the HandlerID in the AbstractClass instead of the MyClass variable. Using Virtual or Abstract isn't valid for variables, so I'm not sure how to do this other than having to implement properties every time a new class is derived.
What I'm trying to do is supply an interface for people to build their own plug-in class and it would use the accessor methods that are supplied with the base class. I don't want to have to implement the same property method every time I create a new instance of the class.
I figured out a way to do what I wanted. This way I can have default getters/setters in the base class and not have to create those in each definition that uses the base. It's not quite what I was looking for, but it'll work.
public abstract class AbstractClass : IBaseClass
{
private int m_HandlerID = 0;
public int HandlerID
{
get { return (this.m_HandlerID); }
set { this.m_HandlerID = value; }
}
private string m_HandlerDescription = "undefined";
public string HandlerDescription
{
get { return this.m_HandlerDescription; }
set { this.m_HandlerDescription = value; }
}
}
public class MyClass: AbstractClass
{
public MyClass()
{
HandlerID = 1;
HandlerDescription = "MyClass";
}
}
class Program
{
static void Main(string[] args)
{
MyClass newClass = new MyClass();
Console.WriteLine("Handler: {0}[{1}]", newClass.HandlerDescription, newClass.HandlerID);
}
}
public abstract class AbstractClass : IBaseClass
{
public AbstractClass(int handlerId)
{
this.HandlerId = handlerId;
}
public int GetHandlerID()
{
return (this.HandlerID);
}
}
public class MyClass : AbstractClass
{
public MyClass():base(1)//specific handler id
}
How about passing the value through the base constructor
The derived class needs able to access the HandlerID to ovewrite it, so you'll need to change it in the abstract class from 'private' to 'protected'.
public interface IBaseClass
{
int GetHandlerID();
}
public abstract class AbstractClass : IBaseClass
{
protected virtual int HandlerID { get; set; }
public virtual int GetHandlerID()
{
return (HandlerID);
}
}
public class MyClass : AbstractClass
{
private int _handlerID = 1;
protected override int HandlerID { get { return _handlerID; } set { _handlerID = value; } }
}
private static void Main(string[] args)
{
var newClass = new MyClass();
Console.WriteLine("HandlerID: {0}", newClass.GetHandlerID());
Console.ReadKey();
}