Getting data from an interface list - c#

Here's the snippet:
interface ITween
{
void DoStuff();
}
public class TweenElement<T> :ITween
{
public Action<T> Setter;
public T from;
public T to;
public float time;
public float currentTime;
public EasingType easing;
public TweenType type;
public bool deleteAtEnd = false;
public Func<bool> Trigger;
public Action Callback;
void ITween.DoStuff() { }
}
private List<ITween> tweens = new List<ITween>();
How do I get data from the list beside deriving from a non generic base class instead of interface? list[o].from doesn't work.

Related

Replacing inheritance with composition in generic classes?

I've been reading a lot about composition and trying to figure how I can refactor my inheritance tree using composition. Currently my class looks like this:
public abstract class BaseClass
{
public abstract string displayText { get; }
public abstract List<Parameter> parameters { get; }
public abstract void FireEvent();
}
public abstract class SubClass<T> : BaseClass
{
private string _displayText;
public override string displayText { get { return _displayText; } }
private List<Parameter> _parameters;
public override List<Parameter> parameters { get { return _parameters; } }
private T _value; // ADDED TO SUBCLASS
public abstract Event<T> Evt { get; } // ADDED TO SUBCLASS
public override void FireEvent()
{
Evt.Raise(_value);
}
}
public class IntClass : SubClass<int>{}
public class StringClass : SubClass<string>{} // more subclasses like this
From my understanding, there is both inheritance and composition going on here.
SubClass Has-A: (Composition)
List of Parameters
Field for Event
Behaviour of Event<T> which is called within it's own FireEvent method
SubClass Is-A: BaseClass (Inheritance)
IntClass/StringClass Is-A: SubClass & BaseClass
The reason for creating BaseClass is because I need polymorphic lists. This way I can create a List<BaseClass> and call FireEvent() on each element in the list and access the displayText and List<Parameter> in a loop.
In the future I will need a sub class which doesn't have an Event and a subclass which will accept a parameter in FireEvent(). Other variants might crop up.
How would I replace my current structure entirely with a composition based approach? Is it even doable?
In this example, you have 3 behaviors. Int uses 3, String uses only 2. If you put the code like this, when you change AnotherServiceB, you don't need to be worry about it break String (since String doesn't have that service)
public class FireEventService<T>
{
private T _value; // ADDED TO SUBCLASS
public abstract Event<T> Evt { get; } // ADDED TO SUBCLASS
public override void FireEvent()
{
Evt.Raise(_value);
}
}
public class AnotherService
{
}
public class AnotherServiceB
{
}
public abstract class SubClass<T> : BaseClass
{
private readonly FireEventService<T> _fireEventService;
private readonly AnotherService _anotherService;
private string _displayText;
public override string displayText { get { return _displayText; } }
private List<Parameter> _parameters;
public override List<Parameter> parameters { get { return _parameters; } }
public SubClass(FireEventService<T> fireEventService, AnotherService anotherService)
{
// All those services should use with interface and Dependency Injection
_fireEventService = fireEventService;
_anotherService = anotherService;
}
public void FireEvent() => _fireEventService.FireEvent();
}
public class IntClass : SubClass<int>
{
private readonly AnotherServiceB _anotherServiceB;
public IntClass(FireEventService<int> fireEventService, AnotherService anotherService, AnotherServiceB anotherServiceB)
: base(fireEventService, anotherService)
{ }
public void DoSomethingUsingServiceB()
{
//_anotherServiceB.DoSomething();
}
}
public class StringClass : SubClass<string>
{
public StringClass(FireEventService<string> fireEventService, AnotherService anotherService)
: base(fireEventService, anotherService)
{ }
}

C# Create Instance of Generic class which inheritance from base

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();
}
}

how to generic type property

Is there a type like enum that would allow me to merge these variable into one
private string StringPropertie;
private int IntPropertie;
private float floatPropertie;
private DateTime DatetimePropertie;
private bool boolPropertie;
to something has follow.
private enumtype property
You can use structure
public struct MyStruct
{
public string StringPropertie;
public int IntPropertie;
public float floatPropertie;
public DateTime DatetimePropertie;
public bool boolPropertie;
}
public class MyClass
{
public MyClass()
{
MyStruct property ;
//...
string str = property.StringPropertie;
}
}

C# casting of derived class

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.

Trying to use virtual-like variable in abstract class instance

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();
}

Categories

Resources