C# Lists and interfaces [duplicate] - c#

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

Related

C#: How do I call non-generic static method in generic class without specifying generic type? [duplicate]

This question already has answers here:
Using static method from generic class
(4 answers)
Closed 2 years ago.
So I have, let's say, some class that requires generic type as a parameter:
public class SomeClass<GType> { }
And there I have a static method that doesn't interact with this generic type in any way:
public static void Method() { }
The problem is, when I try to call this method, it requires me to specify this generic type. I could, in fact, put there any type and that would work, but it just doesn't seem quite right, does it?
public class SomeClass
{
public static void DoSomething()
{
}
}
public class SomeClass<GType> : SomeClass
{
public void DoAnotherThing<GType>()
{
}
}
public static void Main(string[] args)
{
SomeClass.DoSomething();
}

Return generic interface implementation with different generic type

I have created this simple generic interface:
public interface IInitializerSettings<in ViewerType> where ViewerType : Component
{
void Apply(ViewerType dataViewer);
}
And added an implementation for it:
public class MenuSettings : IInitializerSettings<CustomGridLayout>
{
public void Apply(CustomGridLayout dataViewer)
{
Debug.Log("Applied");
}
}
public class CustomGridLayout : CustomLayout
{
// The implementation code
}
Now I try to use it like that:
public IInitializerSettings<CustomLayout> GetDefaultSettings()
{
return new MenuSettings();
}
But I get this error "Cannot convert type MenuSettings to return type IInitializerSettings"
I don't understand why it isn't allowed, CustomGridLayout inherits CustomLayout.
All I could find is this question, but this solution doesn't work for me (I can't use the out keyword).
The reason you cannot do this is because for a contravariant interface (specified by your use of in for the generic type parameter) you cannot implicitly convert it to an instance of a less derived type. I think the bullet points in the docs explains it fairly ok, if you think in terms of IEnumerable<T> (covariant) and Action<T> (contravariant).
As Selvin mentions in the comments the Apply method in MenuSettings expects an instance of CustomGridLayout, so trying to cast MenuSettings to IInitializerSettings<CustomLayout> is not possible because public void Apply(CustomGridLayout dataViewer) cannot handle a CustomLayout as input. Let me give an example:
public class CustomLayout
{
public void SetupCustomLayout() { ... }
}
public class CustomGridLayout : CustomLayout
{
public void SetupGrid() { ... }
}
public class MenuSettings : IInitializerSettings<CustomGridLayout>
{
public void Apply(CustomGridLayout dataViewer)
{
dataViewer.SetupGrid();
}
}
// Later in the code...
var menuSettings = new MenuSettings();
// This cast is what GetDefaultSettings() is trying to do
var genericSettings = (IInitializerSettings<CustomLayout>)menuSettings;
var layout = new CustomLayout();
// Looking at the type of 'genericSettings' this following line should be possible
// but 'MenuSettings.Apply()' is calling 'dataViewer.SetupGrid()' which doesn't exist
// in 'layout', so 'layout' is not a valid input
genericSettings.Apply(layout);
So in relation to the docs you have defined IInitializerSettings<ViewerType> as a contravariant interface, but are trying to use it as a covariant interface - which is not possible.

Best way to implement similar methods of two different classes? [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 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;}
}

Interface vs Class : Defining methods [duplicate]

This question already has answers here:
Interface vs Base class
(38 answers)
Closed 8 years ago.
I'm a bit new to OO programming and I'm trying to understand all facets of this kind of practice : inheritance, polymorphism and such, but there's a thing my brain DOESN'T WANT to fully understand: Interfaces.
I can understand the benefits of using interfacing instead of class-inheritance (mostly because a class can't inherit from multiple parents) but here's where I'm stuck:
Let's say I have something like this:
/** a bunch of interfaces **/
public interface IMoveable
{
void MoveMethod();
}
public interface IKilleable()
{
void KillMethod();
}
public interface IRenderable()
{
void RenderMethod();
}
/** and the classes that implement them **/
public class ClassOne : IMoveable
{
public void MoveMethod() { ... }
}
public class ClassTwo: IMoveable, IKilleable
{
public void MoveMethod() { ... }
public void KillMethod() { ... }
}
public class ClassThree: IMoveable, IRenderable
{
public void MoveMethod() { ... }
public void RenderMethod() { ... }
}
public class ClassFour: IMoveable, IKilleable, IRenderable
{
public void MoveMethod() { ... }
public void KillMethod() { ... }
public void RenderMethod() { ... }
}
By using interfaces here, I would have to declare MoveMethod, KillMethod and RenderMethod each time, in each classes... That means duplicating my code. There must be something wrong, because I don't find this really practical.
So should I implement interfaces only on a few classes? Or should I find a way to mix inheritance and interfaces?
Interfaces are like a contract to a class.. If some class states that it supports such an interface, it must have it's method defined as you properly sampled. Interfaces are great to expose common things that don't easily cross different class implementations.
Now, from your samples, you may be best to do a combination to prevent duplicate code by subclassing from a class and ALSO an interface. So you can get parent-structure code constant and expand as needed.
/** Based on same interfaces originally provided... and the classes that implement them **/
public class ClassOne : IMoveable
{
public void MoveMethod() { ... }
}
public class ClassTwo: ClassOne, IKilleable
{
// Move Method is inherited from ClassOne, THEN you have added IKilleable
public void KillMethod() { ... }
}
public class ClassThree: ClassOne, IRenderable
{
// Similar inherits the MoveMethod, but adds renderable
public void RenderMethod() { ... }
}
public class ClassFour: ClassTwo, IRenderable
{
// Retains inheritance of Move/Kill, but need to add renderable
public void RenderMethod() { ... }
}

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