I have an interface which is implemented by several different objects. What I am trying to do is write a method in c# that will accept the interface object as a parameter and convert this parameter to an object that it implements so i don't have to write the same function for several different types. Such as:
Class UnappliedCashDetails implements interface ITransactionDetail.
Constructor for ISSBatch:
public ISSBatch(List<ITransactionDetail> details)
public static ISSBatch GetNextReceiptBatch()
{
List<UnappliedCashDetail> details = new List<UnappliedCashDetail>();
/`*`some code here to populate my list`*`/
return = new ISSBatch(details);
}
C# does not like this. Am i trying to use the interface wrong or just not casting correctly?
Thanks!
You're passing a List<UnappliedCashDetail> to a constructor that accepts List<ITransactionDetail>. UnappliedCashDetail may very well implement ITransactionDetail, but this type of variance is not supported by C#. Consider that inside the constructor (or any other method) you could attempt to add an instance of SomeOtherTransactionDetail to your details list, except that the details list should really only accept UnappliedCashDetail, as per its declaration.
To make your code work, you need to change your declaration
List<ITransactionDetail> details = new List<ITransactionDetail>();
/* some code here to populate my list */
return new ISSBatch(details);
Or you could simply change your constructor to accept IEnumerable<ITransactionDetail>, in which case your original List<UnappliedCashDetail> declaration would work. Variance is supported for IEnumerable<T> (note: C# 4), since it is just a sequence and cannot be added to, deleted from, etc., so there's no possibility of trying to add an AppliedCashDetail instance to a sequence of UnappliedCashDetail objects.
Related
I am trying to make use of covariant types in order to make generics useful.
I have a generic interface foo that I want to be able to both get and set a property of type T. When declaring the object I don't know what implementing instance I'll be given and so covariance allows for the following declaration
Foo<ibasetype> genericFoo = new implementationOfFoo();
Where implementationOfFoo is
Class implementationOfFoo : Foo<baseTypeA>{}
This works for declaration but it doesn't allow the interface to require an instance of the type baseTypeA as a parameter because covariance only allows returning an instance of the type.
I'm unable to make the interface type invariant as is suggested in other posts because that requires I specifically declare the appropriate class type during object declaration which is not possible as I don't know what instance of implementing class I'll be given.
I am also unable to declare a second type and make that type contravariant as that also triggers a compiler error similar to the invariant case during declaration.
The code that uses this class will handle the appropriate object generation based on reflection prior to passing the object to the implementations various functions so there's no concern of any rule breaking and any exceptions that occur will simply be cleaned up as part of the process of building the code that makes use of the interface.
I assume there's some trick with covariance to get around this shortcoming but I haven't found any guides which discuss this concern. How do I get around this?
Per the responses to my initial question, I would like to be able to build an interface with types of various interfaces I define as the requirements of the main generic interface types. For example
Public interface Foo<typeA> where typeA:iModelA{
typeA prop1{get;set;}
Void doSomething (typeA sameAsProp1)
}
The implementation of the interface must be providing a type which implements iModelA so I simply need to use reflection to determine what the type is and then in my case I use the url provided to construct an instance of that type and pass it to the interface instances ModelA parameter. Then when I need the object I just call the ModelA getter and get from the implementation the iModelA it seems appropriate to provide in that instance.
In my code is declare
Foo fooInstance = getFooInstance(inputs)
For example the page I'm constructing has input fields which on a button click generates a new url which is redirected to. Those same url parameters are then reviewed on the subsequent page load to construct an instance of the base object (which is also based on parameters in the url). The setter logic then reloads the fields based on the passed instance of the iModelA objects parameters.
This logic will be the same regardless of the implementation of the interface so I know its a perfect candidate for an interface and the generic types allow me to impose structure across various objects within the implementation. This if two objects need to reference the exact same type, the generic requirements can manage those needs.
I know that I could get away with not doing a generic interface like so
Interface nonGenericFoo{
iModelA prop1{get;set;}
Void doSomething (iModelA sameAsProp1)
}
However, this means that across functions and properties within the main interface the implementation of the interfaces might be declared differently which will be problematic. In addition, the implementing class will need to make assumptions about the implemention instance which I want to avoid. I want all assumptions to be handled by the main code and let the interface implementations know exactly what they're working with.
I want to create a generic method that takes any class that implements a certain method, for example Print(), usually in such a case we need a common interface and then I would say something like : where T : ICustomInterface and the compiler would guarantee that type T contains any methods in that interface. However, in cases where I do not have access to the type, for example I can not modify the List class part of the System.Collections.Generic namespace to implement my interface, can you still achieve this functionality?
However, in cases where I do not have access to the type, for example I can not modify the List class part of the System.Collections.Generic namespace to implement my interface, can you still achieve this functionality?
Try this first:
public class customList<T> : List<T> where T : ICustomInterface{
}
According to SharpLab, it valid code. But you need proper compiler confirmation.
If it does not work, there is the MVVM way: "If you can not modify it, wrap it into something you can modify." Just put a List<T> inside of a custom class as private field and add all the List Functions you want, by simply relaying thhe cals it to the List<T> inside.
Edit:
I wanted to create a generic class that takes anything that implements an indexer, and then have a generic "Peek" method (look forward in a list, array, or anything that contains an indexer) based on the current state of this class etc
Unfortunately, "having a Indexer" is not something Generics can test. In .NET every class can be given a Indexer, as much as it can be given Functions, Fields and Properties.
Reflection can Identify Indexers. I only ever consider Reflection as a fallback, but it is one way.
Despite the checking limits of generics, you can define Indexers in a Interface, as much as you could Functions and Properties. At the end of the day, Indexers are propably mostly Syntax sugar for Function calls like properties are. While doing so would at a first glance exclude the Build-in List types, it is easy enough to sublcass them and have them implement the Interface.
Without being able to add an interface this is going to be pretty hard to accomplish is a type friendly manner. I don't know the usefulness of this, but it could be done:
public void Print(object myObj) {
var method = myObj.GetType().GetMethod("Print");
if (method != null) method.Invoke(this, null);
}
Can’t do what you’re asking exactly. But you could write a wrapper class that allows you to set a delegate for the required method, and use the wrapper in the type constraint.
class Printable
{
protected readonly Action _action;
public Printable(Action printAction)
{
_action = printAction;
}
public void Print()
{
_action();
}
}
void CallPrint<T>(T obj) where T : Printable
{
obj.Print();
}
var wrapper = new Printable( ()=> foo.Print() );
CallPrint(wrapper)(
You could do a similar thing for classes that have indexers, although you would use a Func instead of an Action.
The problem
I have two interfaces IImporter and IExporter and a class that handles instances of those interfaces:
class IoManager
{
public ReadOnlyCollection<IImporter> Importers { get; }
public ReadOnlyCollection<IExporter> Exporters { get; }
// ...
}
In this class I want to implement a method Add(...) that can add either an importer or an exporter.
I know I could create an overload for both interfaces like
public void Add(IExporter exporter);
public void Add(IImporter importer);
The problem is if I want to add an object that implements both interfaces like CsvIo : IImporter, IExporter via the Add(...) function, I get an ambigious call compiler error because CsvIo is accepted by both overloads.
What I don't want to do
I don't want to rename the overloads to different names, because most types implement both interfaces and I want a coherent behavior for types that implement IExporter, IImporter or both.
I don't want to create a "parent" interface that is implemented by both interfaces, because this seems like a hacky solution
I don't want to cast types in the Add(...) call, like Add((IImporter) CsvIoInstance), because that suggests that only the importer of this type is used. But both overloads check if the object implements both interfaces and adds it to both lists accordingly.
The question
Is there a way of accepting the different types in a coherent manner (so that the call looks the same for each type)?
Edit
To clarify my implementation: this is part of a plugin system. I want to add multiple ways of storing my data (so that it can be used by other applications). The IExporter interface is used for storing the data while the IImporter interface loads the data. The IoManager manages all registered plugins. And of course it is possible (and probably common) that a class implements both, exporting and importing of a certain file format. This is why I wanted the Add(...) function to be similar for all cases.
However, thinking about it again (as already stated in the comments) the plugins are only known at runtime which makes ambiguity an obsolete problem I think. So this is only relevant for built in types.
I'd like to focus on one sentence in particular:
I don't want to cast types in the Add(...) call, like Add((IImporter) CsvIoInstance), because that suggests that only the importer of this type is used. But both overloads check if the object implements both interfaces and adds it to both lists accordingly.
Your current design already gives up one of the goals of type safety: to avoid runtime type checking. Ideally, a method that takes an IImporter parameter should only use that parameter as an IImporter. This forms a sort of "contract" between the caller of the method and the implementer: the implementer trusts that the caller will provide what it needs, and the caller trusts that the implementer will only use it in that way. (See also: Principle of least astonishment.)
Imagine that you're a consumer of this class. There is a collection of IImporters and a method with the signature Add(IImporter foo). What would you expect that method to do? I would expect it to add foo to the list of IImporters - I would not expect it to also do something else because my object happened to implement another interface (such as IExporter). Using the type system in this way "betrays" the contract you've established with the caller.
Change your method names to AddImporter and AddExporter, and then have each method only add the parameter to the corresponding list. That solves the problem with overload resolution, and means that the caller is getting exactly what they asked for.
There's an obvious solution to this problem, but you rule it out with this statement:
I don't want to rename the overloads to different names, because most types implement both interfaces and I want a coherent behavior for types that implement IExporter, IImporter or both.
The problem is that you want to do this:
public void Add(IExporter exporter);
public void Add(IImporter importer);
But you don't want to do this:
public void AddExporter(IExporter exporter);
public void AddImporter(IImporter importer);
Why? You can call the first one an "overloaded method", which it technically is, but it's really just two methods with the same name.
Overloading is when you have have a method that does one thing, but you can do it with different sets of parameters. These two methods actually do two different things. One adds an IExporter and one adds an IImporter. So there's nothing 'incoherent' about giving different names to different methods that do different things. It would be much, much worse to add extra interfaces and complication to your classes just to manipulate the compiler.
It's similar to your request for no parent interface, but what you should have is a child interface that combines the two.
public interface IImporterExporter : IImporter, IExporter {
}
Implement it on your class instead of the two separate interfaces:
class ImporterExporter : IImporterExporter {
}
And then write a third overload:
public void Add(IImporterExporter importerExporter) {
// decide what to do if both interfaces are implemented
}
There is a reason why you end up with the ambiguity problem, and that is because either of the overloads could be correct, or maybe even both of them are correct at the same time. You need to resolve the ambiguity by deciding what to do in that case. Since C# does not have type unions, you must declare a separate interface which unifies them.
Note that this is not "hacky", but is actually good design to combine simpler interfaces into more complex ones. This allows for cleaner and more precise code, which is a good thing. But regardless of that, even if you don't like the idea of combining interfaces for some reason, it is still necessary in C# in order to avoid this exact problem.
Without the third interface, all you're left with is looking for something else that both types have in common, and without a parent interface, you're basically just left with object. This would allow for a single method, but you would lose the benefits of the type system.
public void Add(object obj) {
var maybeImporter = obj as IImporter;
var maybeExporter = obj as IExporter;
if (maybeImporter != null && maybeExporter != null) {
// do something if both are implemented
} else if (maybeImporter != null) {
// importer only
} else
// exporter only
}
}
In Short
I want to be able to call a method, the method takes a parameter of type ObservableCollection<Base> but I want to call it with ObservableCollection<Derived>. It says it cannot convert between the two.
Longer
I want to call a WPF Window, in it is a ListBox that will bind to an ObservableCollection. I want the window to display some basic information that are common to two different classes. The classes are Derived1 and Derived2, and are based an BaseClass. I am able to call the method had the type just been BaseClass, but I want to pass a list through.
So I have two collections :
ObservableCollection<Derived1> A;
ObservableCollection<Derived2> B;
And want to be able to call a method like the one below, with the above two collections so I don't need to duplicate code.
public void InitialiseWindow(ref ObservableCollection<BaseClass> List)
{
this.List=List;
}
But it throws an error:
cannot convert from 'ref System.Collections.ObjectModel.ObservableCollection<Derived1>' to 'ref System.Collections.ObjectModel.ObservableCollection<Base>'
Whilst I'm here
Would there be a better way of binding the Collection so changed made in the Window will reflect on the source, instead of using ref?
Solution
I modified the constructor for the Window so that it casts the IEnumerable to a public member of type ObservableCollection. Since the window would only be shown modally, this the member could be accessed after the window closes.
public ObservableCollection<BaseClass> List;
public InitialiseWindow(IEnumerable<BaseClass> List)
{
InitializeComponent();
this.List=new ObservableCollection<BaseClass>(List);
}
If you're exposing it purely for binding purposes, it's sufficient to pass an IEnumerable<BaseClass> reference. The data binding system will automatically inspect the actual instance to see if it implements INotifyCollectionChanged, so it does not need the bound property to be typed explicitly as an ObservableCollection.
Types are different and for ref types must match exactly.
There are cases when you can use derived class in similar way - read on co-variance/contra-variance for C# templates. I.e. you can do
IEnumerable<Object> objects = new List<String>();
because IEnumerable defines it argument as out
public interface IEnumerable<out T> : IEnumerable
Basically, I'm using an ORM (specifically LLBLGen) that creates entity objects for all my tables. All these entity types inherit from a base class (or really a set of them). I want to create an extension method that accepts a List of the base class and returns some string but I want to pass in inherited types without explicitly casting.
For instance, I have a function like:
string GetString(List<EntityBase2> list); // also tried List<IEntityCore>, which the base class implements
And I want to pass it something like this:
List<ProductEntity> products = ... // populate it
string v = GetString(products);
But I get compiler errors.
How can I accomplish creating this helper method. I want to avoid casting if I can but if this is the best way then at least I could would have some confirmation on that.
try this:
string GetString<T>(List<T> list) where T : IEntityCore {...}
that way you get a generic method that takes a list of objects which implement IEntityCore. there's no need to cast and the compiler will make sure that you pass in the right objects. works starting at framework 2.0.