Calling generic method with generic collection - c#

I'm am just getting started with generics, and am confused by how to implement the following scenario.
This is my base class:
public abstract class UnclaimedProperty
{
public abstract string Key { get; }
public virtual void Process() { }
public virtual void Process(string FileName) { }
abstract public void WriteReport<T>(List<T> PropertyRecords, string FileName);
}
In my implementations I would like to pass a concrete list to the override. something like:
public class PennUnclaimed : UnclaimedProperty
{
public override void Process(string FileName)
{
var reportDollarRecords = new List<PennUnclaimed>();
//add items here
WriteReport(reportDollarRecords, "PennCash");
}
public override void WriteReport(List<UnclaimedProperty> PropertyRecords, string FileName)
{
//write report here
}
}
I get error:
'PennUnclaimed' does not implement inherited abstract member
'UnclaimedProperty.WriteReport<T>(List<T>, string)'
What would be the correct way to implement this?

Based on your comments, consider making the abstract class generic.
public abstract class UnclaimedProperty<T> where T : UnclaimedProperty<T> {
public abstract string Key { get; }
public virtual void Process() { }
public virtual void Process(string FileName) { }
abstract public void WriteReport(List<T> PropertyRecords, string FileName);
}
That way the implementation would look like this
public class PennUnclaimed : UnclaimedProperty<PennUnclaimed> {
public override void Process(string FileName) {
var reportDollarRecords = new List<PennUnclaimed>();
//add items here
WriteReport(reportDollarRecords, "PennCash");
}
public override void WriteReport(List<PennUnclaimed> PropertyRecords, string FileName) {
//write report here
}
public override string Key {
get {
return string.Empty; //TODO:return key
}
}
}
The constraint on the abstract class for the generic argument will allow it to be the type of the current class being implemented.

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)
{ }
}

Alternate way for override method in Interface in C#

I'm working on a project that needs to replace concrete class with Interface. Below is the concrete class and its inheritance class
public class CarRepository
{
private string _model;
private string _colour;
public CarRepository(string model, string colour) {
_model = model;
_colour = colour
}
public string Get(GUID id)
{
return id.ToString();
}
protected virtual void DoSomething(ref ISpecial special) {
special = special.AddFields(Rego, ModelNumber)
}
}
public class BigCarRepository : CarRepository
{
public class BigCarRepository(string model, string colour)
: base(model, colour)
protected override void DoSomething(ref ISpecial special) {
special = special.AddFields(SpecialOffer, OptionPack)
}
}
I want to replace the inheritance of a concrete class for BigCarRepository from CarRepository with an interface (i.e. ICarRepository). Thus I created an interface and replacing the concrete class but couldn't find a way to address the override method. I have created the interface below and modified my concrete classes and the inheritance but stuck at the override method.
public interface ICarRepository
{
string Get(string id);
}
public class CarRepository : ICarRepository
{
private string _model;
private string _colour;
public CarRepository(string model, string colour) {
_model = model;
_colour = colour
}
public string Get(GUID id)
{
return id.ToString();
}
protected virtual void DoSomething(ref ISpecial special) {
special = special.AddFields(Rego, ModelNumber)
}
}
public class BigCarRepository : ICarRepository
{
public ICarRepository _carRepository { get; set; }
public BigCarRepository(ICarRepository carRepository)
{
_carRepository = carRepository;
}
public string Get (string id)
{
return _carRepository.Get(id);
}
**protected override void DoSomething(ref ISpecial special) {
special = special.AddFields(SpecialOffer, OptionPack)
}**
}
Update:
If you need to make an abstraction of CarRepository. You did well by extracting the interface. You also need to add all methods that you want your derived classes to implement.
public interface ICarRepository
{
string Get(string id);
void DoSomething(ref ISpecial special);
}
public class BigCarRepository : ICarRepository
{
public ICarRepository _carRepository { get; set; }
public BigCarRepository(ICarRepository carRepository)
{
_carRepository = carRepository;
}
public string Get (string id)
{
return _carRepository.Get(id);
}
public void DoSomething(ref ISpecial special) {
special = special.AddFields(SpecialOffer, OptionPack);
}
}
If this is what you want, you're fine.
In my previous answer, i suggested that you might need to reuse some logic of base class CarRepository , but still wanted to force BigCarRepository to implement his own logic of DoSomething. This could be usefull if you have the same code being reused in derived classes.
public abstract class CarRepository : ICarRepository
{
private string _model;
private string _colour;
protected CarRepository(string model, string colour) {
_model = model;
_colour = colour
}
public string Get(GUID id)
{
return id.ToString();
}
public absctract void DoSomething(ref ISpecial special); // Force all derived classes to implement this method
protected virtual void DoSomethingBase(ref ISpecial special) {
special = special.AddFields(Rego, ModelNumber)
}
}
public class BigCarRepository : CarRepository
{
public ICarRepository _carRepository { get; set; }
public BigCarRepository(ICarRepository carRepository) : base (pass_the_model, pass_the_colour)
{
_carRepository = carRepository;
}
public override void DoSomething(ref ISpecial special) {
DoSomethingBase(ref special); // if you need some base class logic
special = special.AddFields(SpecialOffer, OptionPack);
}
}

Call parent constructor but keep the reference of the child C#

I am calling the base constructor but somehow I need to point to the child one back. Take a look at the example bellow:
//Child
public CompanyEventsView(IAggregator aggregator, IRepository<CompanyEvents> repository, int i)
: base(aggregator, repository, i)
{
}
//Base
public BaseViewModelFor(IAggregator aggregator, IRepository<TSource> repository, int i)
{
Aggregator = aggregator;
var source = repository.GetKey(i);
this.MapFromSourceObject(source); // So "This" here should be pointing to the child class
}
Is there any way of doing this?
this and base do not refer to different instances, they are the same.
If your MapFromSourceObject method is defined in the child class, you can cast this to the child type like: (this as CompanyEventsView).MapFromSourceObject(source).
But this would defeat the whole point of inheritance.
Maybe define MapFromSourceObject as abstract or virtual in the base class?
If your base class depends the implementations of child classes, making the class itself abstract would be a better idea.
Maybe this example helps you a little bit with inheritance:
namespace CSharpConsoleApplication.Tests
{
using System;
using System.Collections.Generic;
using System.Linq;
class TemporaryTest
{
public static void Run()
{
Mother<FirstCompanyEvent> firstChild = new FirstChild(new FirstCompanyEvent("this is wrong"));
firstChild.Print();
Mother<SecondCompanyEvent> intChild = new SecondChild(new SecondCompanyEvent("you are too young to do this"));
intChild.Print();
}
}
public abstract class BaseCompanyEvent
{
protected string Value { get; private set; }
public BaseCompanyEvent(string value)
{
Value = value;
}
public abstract string GetMessage();
}
public class FirstCompanyEvent : BaseCompanyEvent
{
public FirstCompanyEvent(string value)
: base(value)
{ }
public override string GetMessage()
{
return "First born: " + Value;
}
}
public class SecondCompanyEvent : BaseCompanyEvent
{
public SecondCompanyEvent(string value)
: base(value)
{ }
public override string GetMessage()
{
return "Younger brother: " + Value;
}
}
public abstract class Mother<T> where T : BaseCompanyEvent
{
protected T CustomEvent { get; private set; }
public Mother(T customEvent)
{
CustomEvent = customEvent;
}
public abstract void Print();
}
public class FirstChild : Mother<FirstCompanyEvent>
{
public FirstChild(FirstCompanyEvent e)
: base(e)
{ }
public override void Print()
{
Console.WriteLine(CustomEvent.GetMessage());
}
}
public class SecondChild : Mother<SecondCompanyEvent>
{
public SecondChild(SecondCompanyEvent e)
: base(e)
{ }
public override void Print()
{
Console.WriteLine(CustomEvent.GetMessage());
}
}
}

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

Extending a base class method

I am new to C# and am trying to understand basic concepts. Thank you in advance for your help. I have some sample classes below (typed in this window so there may be some errors)and have two questions:
Is it possible to Call a derived class method that executes the code in the base class method with the same name, then executes the code in the derived class method? Every derived class will need to perform the base class code for the RunCheck then do specialized code specific to its class. I could name RunCheck() something else in the base class and then call it when I call the RunCheck() of the derived class but then I have to remember to call it on the RunCheck() in the derived class.
In the Program.cs I want to output all fields with a blank value if it is on a field that is not in the derived class I pass in. What would I pass in?
Here is my code:
class baseCheck
{
public DateTime StartTime { get; set; }
public DateTime LastRun { get; set; }
public int Runs { get; set; }
//Others
public void RunCheck()
{
if (Started != null)
started = DateTime.Now;
LastRun = DateTime.Now;
Runs++;
}
}
class FileCheck : baseCheck
{
public string FileName { get; set; }
public void RunCheck()
{
//I want all the code in the base class to run plus
//any code I put here when calling this class method
}
}
class DirectoryCheck : baseCheck
{
public string DirectoryName { get; set; }
public void RunCheck()
{
//I want all the code in the base class to run plus
//any code I put here when calling this class method
}
}
//Program.cs
static void Main()
{
//Create derived class - either DirectoryCheck or FileCheck
//depending on what the user chooses.
if (Console.ReadLine()=="F")
{
FileCheck c = new FileCheck();
}
else
{
DirectoryCheck c = new DirectoryCheck();
}
PrintOutput(c);
}
private void PrintOut(What do I put here?)
{
Console.WriteLine("Started: {0}",f.StartTime)
Console.WriteLine("Directory: {0}", f.DirectoryName)
Console.WriteLine("File: {0}", f.FileName}
}
Just call base.RunCheck() in your DirectoryCheck class:
public class DirectoryCheck : baseCheck
{
public string DirectoryName { get; set; }
public void RunCheck()
{
//I want all the code in the base class to run plus
//any code I put here when calling this class method
base.RunCheck();
Console.WriteLine("From DirectoryCheck");
}
}
Also with your current implementation you are hiding the base class RunCheck() method - you should really override it - this changes the method signature in the base class to
public virtual void RunCheck()
and in the derived classes to
public override void RunCheck()
I suspect what you really want though is something like the Non Virtual interface pattern (NVI) - Expose a protected virtual method in your base class, that child classes can override, but have a public method on the base class that is actually calling that method internally - this approach allows you to extend what you are doing before and after that call.
In your example this would look like this:
class BaseCheck
{
private DateTime Started { get; set; }
public DateTime StartTime { get; set; }
public DateTime LastRun { get; set; }
public int Runs { get; set; }
//Others
public void RunCheck()
{
if (Started != null)
Started = DateTime.Now;
LastRun = DateTime.Now;
Runs++;
CoreRun();
}
protected virtual void CoreRun()
{
}
}
public class DirectoryCheck : BaseCheck
{
public string DirectoryName { get; set; }
protected override void CoreRun()
{
//I want all the code in the base class to run plus
//any code I put here when calling this class method
Console.WriteLine("From DirectoryCheck");
}
}
In a derived class, you can call the method in the base class using:
public override void RunCheck()
{
base.RunCheck();
// Followed by the implementation of the derived class
}
As mentioned in the comments, the base method will need to be declared as virtual to allow overriding:
public virtual void RunCheck() { ... }
For your PrintOut() method, there is no magic way, but you could have it take the base class as a parameter, and then test for the type.
private void PrintOut(baseCheck f)
{
Console.WriteLine("Started: {0}", f.StartTime)
Console.WriteLine("Directory: {0}", f.DirectoryName)
if (check is FileCheck)
{
Console.WriteLine("File: {0}", ((FileCheck)f).FileName}
}
}
Or you could use overloads:
private void PrintOut(baseCheck f)
{
Console.WriteLine("Started: {0}", f.StartTime)
Console.WriteLine("Directory: {0}", f.DirectoryName)
}
private void PrintOut(FileCheck f)
{
PrintOut((baseCheck)f);
Console.WriteLine("File: {0}", ((FileCheck)f).FileName}
}
Or you could have your PrintOut method part of your class (maybe even use the existing ToString() method) and override it as required.

Categories

Resources