Best way to implement similar methods of two different classes? [closed] - c#

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I have two classes (A and B) which implements the same interface (I) in C#. The interface have 5 methods to implement. Implementations of two of those methods are almost the same in both A and B except each implemetation uses a different variable. Here is the abstract layout of my classes.
class A : I
{
Folder folder;
void method()
{
//implementation uses ``folder``
}
class B : I
{
List list;
void method()
{
//implementation uses ``list``
}
}
Because the implementation of Method is the same (except the one parameter) I want to have implement Method only once. What is the best solution according of design patterns? one simple option is to define a third class which implements Methodand takes one parameter (either list or folder) and then call it within the Method of A and B. Any other solution?
------------Edit---------------
I don't want my Method to get any extra parameter. Under such circumstances, isn't static util class a better option than defining an abstract class?

You can create a shared abstract base class which takes a T generic parameter and implements I<T>. That same T will be passed to Method, which will be implemented in the base class:
public interface I<T>
{
void Method(T t);
}
public abstract class Base<T> : I<T>
{
public Base(T t)
{
this.param = t;
}
private readonly T param;
public void Method()
{
// Do stuff
}
}
public class A : Base<Folder>
{
public A(Folder folder) : base(folder)
{ }
}
public class B : Base<List>
{
public B(List list) : base(list)
{ }
}
public class Folder { }
public class List { }
Now, you can do:
static void Main()
{
var a = new A(new Folder());
a.Method();
var b = new B(new File());
b.Method();
}

One option is to use an abstract class instead of an interface. Of course this class must be generic.
Second option is to extract method to "static utils" class and in both use this "utils". But this assumes that list and folder are instances of same interface.
In my opinion the first option is the best one.

If the method's implementations differ only by a variable's type consider using Template Method pattern combined with a generic base class.
abstract class Base<T> : I
{
public void method()
{
var items = GetItems();
HandleItems(items);
}
protected abstract IEnumerable<T> GetItems();
void HandleItems(IEnumerable<T> items)
{
// do something with a sequence
foreach(var item in items) Console.WriteLine(item);
}
}
class A : Base<FolderItem>
{
Folder folder;
protected overrides IEnumerable<FolderItem> GetItems() {return folder.Items;}
}
class B : Base<ListItem>
{
List list;
protected overrides IEnumerable<ListItem> GetItems() {return list.Items;}
}

Related

Static method in generic class causes CA1000 warning [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed last year.
Improve this question
I'm working on a library to manage objects (Animals in my sample code). I have a base class named Animal and a generic class named SpecificAnimal. I also have Dog, Cat etc. which are implemented with the SpecificAnimal class.
If a user wants to create a dog, it is as simple as:
var myDog = new Dog()
{
Name = "Rover",
Age = 3
};
myDog.Add();
The class hierarchy looks like this:
Animal Class
public abstract class Animal
{
public static Animal GetByName(string animalName)
{
// Code that can read any kind of animal from a database
// and create an instance of the correct type
throw new NotImplementedException();
}
public static Animal GetById(int animalId)
{
// Code that can read any kind of animal from a database
// and create an instance of the correct type
throw new NotImplementedException();
}
public string Name { get; set; } = string.Empty;
public int Age { get; set; }
public void Add()
{
// Add this Animal to the database
}
public void Update()
{
// Update this animal
}
}
Generic SpecificAnimal class
public abstract class SpecificAnimal<T> : Animal where T : SpecificAnimal<T>
{
public static string Genus { get; protected set; } = String.Empty;
public new static T GetByName(string animalName)
{
// Code that can read an object of type T from a database
return (T)Animal.GetByName(animalName);
}
public new static T GetId(int animalId)
{
// Code that can read an object of type T from a database
return (T)Animal.GetById(animalId);
}
}
Dog class
public class Dog : SpecificAnimal<Dog>
{
public Dog()
{
Genus = "Canis";
}
// Dog specific properties and methods
}
This code is working and (in my opinion) is easy for the consumer of the library to use.
My problem is that the static properties and methods in the SpecificAnimal class generate the warning:
CA1000: Do not declare static members on generic types
https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1000
The documentation for CA1000 says "Do not suppress..." but, it doesn't suggest a better solution. If I shouldn't have static members in a generic class, what should I be doing?
The documentation says that static methods in a generic type are bad because of this awkward syntax:
var myDog = SpecificAnimal<Dog>.GetByName("Rover");
I agree but, my users should never do that. Although, I don't know of a way to prevent it.
How can I add static members to a generic class without generating CA1000? How can I protect the SpecificAnimal class so that the user only has access to Dog and Animal?
The warning exists because there's risk that the behavior might be different than the programmer expects. However, sometimes it's a useful pattern. I ran into this a few weeks ago when building a library.
Let's look at a more simplified example:
void Main()
{
Baz<string>.Counter++;
Baz<int>.Counter++;
Console.WriteLine(Baz<object>.Counter);
}
public abstract class Foo
{
public static int Counter { get; set; }
}
public class Baz<T> : Foo
{
}
What is output? It's easy to think the output would be 0 because Baz<object> is a different closed generic type than Baz<string> or Baz<int>. In fact, the output is 2 because both post increment operations affect the same static variable.
The property can be rewritten as in the example.
public abstract class SpecificAnimal<T> : Animal where T : SpecificAnimal<T>
{
public virtual string Genus { get; } = String.Empty;
}
public class Dog : SpecificAnimal<Dog>
{
public override string Genus { get; } = "Canis";
}
Note that implementing the static new method does not work in the same way as inheritance.

C# Lists and interfaces [duplicate]

This question already has answers here:
Convert List<DerivedClass> to List<BaseClass>
(13 answers)
Closed 2 years ago.
I would like to pass a method a List of a custom type that conforms to an interface. I'd like the method parameter to be a List of the particular interface type.
Is this possible? I can see I can do this if I use an array instead of a List. I've added my code below to help clarify my problem.
public interface TeamMoveCTRL_IF
{
}
public class TeamMember: TeamMoveCTRL_IF
{
}
public class TeamCTRL
{
public TeamMember[] team1;
public List<TeamMember> team2;
void Start()
{
TestArray(team1); //Works
TestListElement(team2[0]); //Works
TestList(team2); //Error because team2 is List<TeamMember>
}
private void TestList(List<TeamMoveCTRL_IF> team )
{
}
private void TestArray(TeamMoveCTRL_IF[] team)
{
}
private void TestListElement(TeamMoveCTRL_IF member)
{
}
}
It's not allowed. Consider this:
interface I {}
class A : I {}
class B : I {}
void Fn(List<I> lst) =>
lst.Add(new B());
static void Main() =>
Fn(new List<A>());
If you were allowed to change the type of the parameter to a list of its interface, you'd be allowed to add anything derived from that interface in the list, whereas the original definition only allows A elements. You'd be breaking the definition of the list.
What you trying to do is not correct.
There are multiple ways to achieve what you need but it depends on context.
Start from following change and go from there.
public List<TeamMoveCTRL_IF> team2;
You can use this approach:
private void TestList<T>(IEnumerable<T> team)
where T : TeamMember
{
}
Instead of this two implementations:
private void TestList(List<TeamMoveCTRL_IF> team )
{
}
private void TestArray(TeamMoveCTRL_IF[] team)
{
}

C# equivalent of <? extends Type>? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm working in C#. I created an interface in my code which is called EntityInterface. I wrote this function:
private void Save(List<EntityInterface> entities)
{ ... }
Elsewhere in my code, I have a variable which is defined as List<Job>. The Job class is a class that implements EntityInterface.
I cannot pass my list of Job objects to the Save method. The compiler complains that the parameter is of the wrong type, because List<Job> is not the same as List<EntityInterface>.
I need to modify the function to express the idea that the parameter can be a "list of any object that implements EntityInterface". I have searched around but can't find an example of how to do this.
Your model should look something like this:
using System.Collections.Generic;
public interface IEntity
{
void Save<T>(List<T> entities) where T : IEntity;
}
public class Job : IEntity
{
void IEntity.Save<T>(List<T> entities) { }
}
public class TargetImpl : IEntity
{
void IEntity.Save<T>(List<T> entities) { }
}
and as a test to step through:
using System.Collections.Generic;
using Xunit;
public class UnitTest1
{
[Fact]
public void Test1()
{
IEntity ientity = new TargetImpl();
ientity.Save(new List<Job>());
}
}
One caveat being the example above implements the IEntity interface explicitly (for brevity) as such child implementations must be explicitly referenced via that interface. For a similar but subtly different implementation you could also do:
public class Job : IEntity
{
public void Save<T>(List<T> entities) where T : IEntity { }
}
public class TargetImpl : IEntity
{
public void Save<T>(List<T> entities) where T : IEntity { }
}
and the test impl can (optionally) change to :
[Fact]
public void Test1()
{
targetImpl ientity = new TargetImpl();
ientity.Save(new List<Job>());
}

How to cast a List<MyModel> to List<object> [duplicate]

This question already has answers here:
Shorter syntax for casting from a List<X> to a List<Y>?
(7 answers)
Closed 7 years ago.
I'm not sure if what I am trying to do is setup correctly so I am asking for help.
I have a base class, A, that has a public virtual MethodA(...).
In Method A I have the following statement:
var recordToValidate = GetBulkRecordsToBeValidated(profileId);
< more code that uses recordToValidate >
In the base class A I define GetBulkRecordsToBeValidated as follows:
internal virtual List<object> GetBulkRecordsToBeValidated(int profileId)
{
throw new NotImplementedException();
}
I have other classes that inherit from Class A (i.e. Class B inherits from Class A, Class C inherits from Class A, etc).
Each inherited class overrides the GetBulkRecordsToBeValidated which makes a call to the database to return the specific records for that entity. Each entity returns a different model which is why in the base class I have the method return a List of object.
In Class B it looks like this:
internal override List<object> GetBulkRecordsToBeValidated(int profileId)
{
return makes call to database which returns a List<ModelBRecords>
}
In Class C it looks like this:
internal override List<object> GetBulkRecordsToBeValidated(int profileId)
{
return makes call to database which returns a List<ModelCRecords>
}
The problem is I am getting the following error in Class B and Class C on the return:
Cannot convert expression type System.Collection.Generic.List ModelBRecords to return type System.Collection.Generic.List object
What do I need to do so I can return different list types to the call to GetBulkRecordsToValidate in Method A of the Base Class A?
As a quick fix, use .Cast<Object>.ToList().
However, you might want to consider making the base class generic like this:
public class A<T>
{
public void MethodA()
{
List<T> recordToValidate = GetBulkRecordsToBeValidated(profileId);
....
}
internal virtual List<T> GetBulkRecordsToBeValidated(int profileId) // you might want to make this an abstract method instead of virtual
{
....
}
}
public class C : A<ModelCRecords>
{
internal override List<ModelCRecords> GetBulkRecordsToBeValidated(int profileId)
{
return makes call to database which returns a List<ModelCRecords>
}
}
You can create generic class
class A<T>
{
public virtual List<T> GetBulkStuff() { throw new Exception(); }
}
class B : A<ModelBRecords>
{
public override List<ModelBRecords> GetBulkStuff()
{
return base.GetBulkStuff();
}
}

How to make a generic singleton base class C# [duplicate]

This question already has answers here:
What's a good threadsafe singleton generic template pattern in C#
(23 answers)
Closed 9 years ago.
I am trying to create a generic singleton base class like
public class SingletonBase<T> where T : class, new()
{
private static object lockingObject = new object();
private static T singleTonObject;
protected SingletonBase()
{
}
public static T Instance
{
get
{
return InstanceCreation();
}
}
public static T InstanceCreation()
{
if(singleTonObject == null)
{
lock (lockingObject)
{
if(singleTonObject == null)
{
singleTonObject = new T();
}
}
}
return singleTonObject;
}
}
But I have to make constructor as public in derived one.
public class Test : SingletonBase<Test>
{
public void A()
{
}
private Test()
: base()
{ }
}
Compilation Error:
'Test' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'Test'
How can I achieve this?
The problem is your generic constraint where T : class, new(). The new() constraint requires a public, parameterless constructor on T. There is no way around this; you need to provide such a constructor in Permission Controller.
I would avoid this kind of recursive generic pattern. Read this this blog post for a detailed explanation of the pattern and reasons not to use it.
As far as I can tell, you don't need to have any sub-classes of SingletonBase<T>. I can't see anything that a subclass of SingletonBase<T> would be able to add to your code. I would simply rewrite it as
public static class Singleton<T> where T : class, new()
{
...
}
You can then use it as
var test = Singleton<Test>.Instance;
If you want to be able to use Test as a singleton, create it as
public class Test
{
public static T Instance
{
get { return Singleton.Instance<Test>; }
}
}

Categories