I have an interface that extends some other interface, like this:
interface IBase
{
int Id { get; set; }
string Name { get; set; }
}
interface IExtended : IBase
{
bool IsChecked { get; set; }
}
Then I use base interface as a parameter in a delegate function that is also a parameter to class constructor, like this:
public class SomeClass
{
private IBase _model;
private Func<IBase, string> _handler;
public SomeClass(IBase model, Func<IBase, string> handler)
{
_model = model;
_handler = handler;
}
public string ExecuteHandler()
{
return _handler(model);
}
}
Interface implementations:
public class BaseImplementation : IBase
{
int Id { get; set; }
string Name { get; set; }
public BaseImplementation(int id, string name)
{
Id = id;
Name = name;
}
}
public class ExtendedImplementation : IExtended
{
int Id { get; set; }
string Name { get; set; }
bool IsChecked { get; set; }
public BaseImplementation(int id, string name, bool isChecked)
{
Id = id;
Name = name;
IsChecked = isChecked;
}
}
Intended use:
BaseImplemetation baseModel = new BaseImplementation(1, "base");
ExtendedImplemetation extendedModel = new ExtendedImplementation(2, "extended", true);
SomeClass someClass1 = new SomeClass(baseModel, (IBase arg) => {
Console.Write("Remember, " + arg.name + ", YOLO!");
});
SomeClass someClass2 = new SomeClass(extendedModel, (IExtended arg) => {
Console.Write(arg.name + ", YOLO! You're " + (arg.IsChecked) ? "checked!" : "not checked!");
});
string res1 = someClass1.ExecuteHandler();
string res2 = someClass2.ExecuteHandler();
But that ( doesn't work, even though implementation of IExtended would necessarily implement everything that is defined by IBase interface. Why is that so and how would I bypass this and get the result I want?
EDIT:
I think I got it now.
I thought that Func<IBase, string>
is equal to Func<IExtended, string>
because IExtended of course implements everything that IBase does, so there should be no problem, right? Implementation as I wanted it to be and is listed in my example would of course work just fine.
BUT! The problem is that someClass2 can't be constructed like that because, as @Servy mentioned, delegate function could do something like this:
SomeClass someClassWrong = new SomeClass(baseModel, (IExtended arg) => {
if (arg.IsChecked) {
// gotcha, baseModel doesn't have IsChecked property!
}
});
EDIT 2:
Thank you everybody for you help and sorry for constant editing and giving wrong example sof what I want :D
But that doesn't work, even though implementation of
IExtended
would necessarily implement everything that is defined byIBase
interface. Why is that so and how would I bypass this and get the result I want?
When SomeClass
invokes that delegate it might not actually pass an IExtended
instance . It's allowed to provide any IBase
instance as the parameter, so if it provides one that doesn't implement IExtended
, then what would you expect your delegate to do?
If SomeClass
is always going to pass an IExtended
instance, then modify the delegate it accepts in its constructor accordingly, so that the callers always know they're getting an IExtended
instance as a parameter.
You can simply define a delegate that knows the IBase
is really an IExtended
:
SomeClass someClass = new SomeClass((IBase arg) => { (arg as IExtended).DoSomethingOnlyExtendedKnowsAbout(); });
This is potentially unsafe, but if you somehow can enforce that the arg
passed to that specific lamda will always be an IExtended
then there is no harm. You could also provide a safety mechanism in the lambda itself and manage it accordingly up the call stack:
SomeClass someClass = new SomeClass((IBase arg) => { (arg as IExtended)?.DoSomethingOnlyExtendedKnowsAbout(); });
I don't see the problem. Based on the code you have, the following works as intended:
public class SomeClass
{
public SomeClass(Func<IBase, string> handlerFcn)
{
// something gets done
this.Handler=handlerFcn;
}
public Func<IBase, string> Handler { get; set; }
}
public static class Program
{
static void Main(string[] args)
{
var s1 = new SomeClass((x) => x.SomeMethod());
var xt = new ExtendedClass();
var result = s1.Handler(xt);
// result = "yolo extended edition!"
}
}
I think you were trying to use the concrete class ExtendedClass
in the lambda definition and that won't work unless you define it as a closure .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.