Getter and setter coming from different interfaces - c#

I really need to have something like this:
interface IReadableVar
{
object Value { get; }
}
interface IWritableVar
{
object Value { set; }
}
interface IReadableWritableVar : IReadableVar, IWritableVar
{
}
However when I try to use IReadableWritableVar.Value I get compile errors unless I explicitly cast to base interface, like here:
static void Main()
{
IReadableWritableVar var = null;
var t = var.Value; // <-- CS0229: Ambiguity between 'IReadableVar.Value' and 'IWritableVar.Value'
var.Value = null; // <-- CS0229: Ambiguity between 'IReadableVar.Value' and 'IWritableVar.Value'
var v = ((IReadableVar)var).Value; // compiles fine
((IWritableVar)var).Value = null; // compiles fine
}
Why do I get these errors although everything should be clear to the compiler? Is there any way to fix this problem other than casting (hundreds of places in the application)?
Update: it was suggested this is a dupe of Implementing 2 Interfaces with 'Same Name' Properties but this is slightly different as in the other case there's no inheritance in interfaces. Anyway, the problem is solved now - see accepted answer.

A possible workaround can be modify your interface IReadableWritableVar like this:
interface IReadableWritableVar : IReadableVar, IWritableVar
{
new object Value { get; set; }
}
But keep in my that a valid implementation should be:
class ReadableWritableVar : IReadableWritableVar
{
public object Value
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
object IWritableVar.Value
{
set { throw new NotImplementedException(); }
}
object IReadableVar.Value
{
get { throw new NotImplementedException(); }
}
}
A more concrete example:
class ReadableWritableVar : IReadableWritableVar
{
public object Value
{
get { return ((IReadableVar)this).Value; }
set { ((IWritableVar)this).Value = value; }
}
object _val;
object IWritableVar.Value { set { _val = value; } }
object IReadableVar.Value => _val;
}
Or even better:
class ReadableWritableVar : IReadableWritableVar
{
public object Value { get; set; }
object IWritableVar.Value { set { Value = value; } }
object IReadableVar.Value => Value;
}

Interesting question. I think extension methods will help in this case.
public static class Extension
{
public static object GetValue(this IReadableVar v)
{
return v.Value;
}
public static void SetValue(this IWritableVar v, object value)
{
v.Value = value;
}
}
You need to change the code to use it:
IReadableWritableVar variable = null;
var t = variable.GetValue();
variable.SetValue(null);
The extension method does the cast for you.

Well, effectively Getter and Setter are just two methods. When we use IReadableWritableVar interface there are two methods with identical name inherited from base interfaces and compiler doesn't know which of these two should it use hence the ambiguity.
When we cast that to one of these interfaces the other member's gone and there's no error.
If we implement those member there will be no error as compiler will use that implementation:
class ReadableWritableVar : IReadableWritableVar
{
public object Value { get; set; }
}
var #var = new ReadableWritableVar();
var t = #var.Value;
Also you can use an explicit interface members implementation from #Alessandro D'Andria's answer if it is required that you use interface and not class.

using abstract class istead of interface will resolve your problem.
public abstract class ReadableWritableVar : IReadableVar, IWritableVar
{
public object Value { get; set; }
}

One possible alternative is to use explicit (java style) get and set methods instead of a property:
interface IReadableVar
{
object GetValue();
}
interface IWritableVar
{
void SetValue(object value);
}
interface IReadableWritableVar : IReadableVar, IWritableVar
{
}
The usage then becomes:
static void Main(string[] args)
{
IReadableWritableVar aVar = null;
var t = aVar.GetValue();
aVar.SetValue(null);
}

Related

How can I force-cast a data to the generics specified in the method constraint?

I have the following data class and VM class:
public interface IData
{
string Name
{
get;
}
}
public class DataPartial: IData
{
public DataPartial()
{
}
public string Name => "Data partial";
}
public class DataFull : IData
{
public string Name => "Data full";
public DataFull()
{
}
}
public interface IVM
{
IData Data { get; }
}
public interface IVM_partial: IVM
{
new DataPartial Data { get; }
}
public class VM_Partial : IVM_partial
{
public VM_Partial()
{
Data = new DataPartial();
}
public DataPartial Data { get; set; }
IData IVM.Data => Data;
}
public interface IVM_Total:IVM_partial
{
new DataFull Data { get; }
}
public class VM_Total : IVM_Total
{
public VM_Total(IVM_partial dataA)
{
Data = new DataFull();
DataA_interface = dataA;
}
public IVM_partial DataA_interface { get; }
public DataFull Data { get; private set; }
DataPartial IVM_partial.Data => DataA_interface.Data;
IData IVM.Data => Data;
}
public static class RunVM<T, VM>
where T: class, IData
where VM :class, IVM
{
public static T RunMe(VM hi)
{
var vmA = (hi as VM); //how to force-cast this to the VM type??!!
return (T)vmA.Data;
}
}
class Program
{
static void Main(string[] args)
{
VM_Partial partialData = new VM_Partial();
var VMClass = new VM_Total(partialData);
RunVM<DataFull, IVM_Total>.RunMe(VMClass);
RunVM<DataPartial, IVM_partial>.RunMe(VMClass); //here it throws exception because I can't force cast the IVM to IVM_partial
}
}
At the method RunVM<DataPartial, IVM_partial>.RunMe(VMClass);, I want it to return me the DataPartial object, which I know it's there in the object VMClass, but I cannot get it done.
I will get an InvalidCastException when I am at the RunMe method, because the parameter hi is always VMClass, and I can never get it to behave like IVM_partial class. In other words, I can't cast hi to a more basic interface IVM_partial.
How to cast hi to a more basic interface IVM_partial? Is it possible at all, and if not, why not?
It's not the cast that's the problem - it's that you expect the compiler (or runtime) to pick up on the fact that the cast is to a type that declares a new Data property.
This line in RunMe:
return (T)vmA.Data;
... will always use the Data property declared by IVM, because that's the only property the compiler knows about when it's compiling that method. It doesn't matter that you're casting to another interface that contains a new Data property... the cast is about an execution-time check; it doesn't change which Data property the method uses.
It's unclear to me exactly what you're trying to achieve here, but I strongly suspect that you'll need to change tack significantly - maybe by adding another generic type parameter into the mix, maybe by using polymorphism more, or maybe changing the design more radically.

Return IEnumerable<IMyInterface> from List<MyInterfaceClass>

EDIT: This question would be invalid in .NET 4 since it actually works as desired.
I have a Data class that must implement an interface like this:
public interface IData
{
IEnumberable<IOther> OtherList { get; }
IOther AddOther();
void RemoveOtherData(IOther data);
}
But I am stuck with declaring the actual member in Data
public class Data : IData
{
// desired, always return the same reference
public IEnumberable<IOther> OtherList { get { return _mOtherList } }
// Non persistent reference not desirable.
public IEnumerable<IOther> OtherList { get { return _mOtherList.Select(x => x as IOther); } }
List<IOther> _mOtherList = new List<Other>(); // error, type mismatch
List<Other> _mOtherList = new List<Other>(); // error, property return type mismatch
IEnumerable<IOther> _mOtherList = new List<Other>(); // ok, but cannot use List methods without casting.
}
What would be the best solution in this case?
public class Data : IData
{
public IEnumerable<IOther> OtherList { get; private set; }
List<Other> _mOtherList = new List<Other>();
public Data()
{
OtherList=mOtherList.Cast<IOther>();
}
}
On .net 4 IEnumerable<out T> is co-variant. i.e. a class that implements IEnumerable<Other> automatically implements IEnumerable<IOther> too. So could also simply write:
public class Data : IData
{
public IEnumerable<IOther> OtherList { get{return mOtherList;} }
List<Other> _mOtherList = new List<Other>();
}
But I'd avoid that, since it breaks encapsulation and allows outsiders to modify your list.
((List<Other>)MyData.OtherList).Add(...);
Other class must implement IOther interface and you don't need to cast.
When you declare _mOtherList, it's IEnumerable, so you can't use list methods. Declare it as a list.
public class Data : IData
{
List<IOther> _mOtherList = new List<Other>();
public IEnumberable<IOther> OtherList { get { return _mOtherList } }
IOther AddOther()
{
return null;
}
void RemoveOtherData(IOther data){}
}
Your Other class:
class Other : IOther
{
//some members
}
As IEnumerable is covariant this is fine:
public interface IInterface{}
public class ClassA : IInterface{}
public class ClassB
{
private readonly List<ClassA> _classAs;
public IEnumerable<IInterface> Data{ get { return _classAs; } }
}

Add object which does not implement interface, but meets all qualifications, to a list expecting interface

I have the following:
List<IReport> myList = new List<IReport>();
Report myReport = TheirApi.GetReport();
myReport meets all the qualifications of IReport, but cannot implement IReport because I do not have access to the source of TheirApi. Casting to type IReport obviously results in null, and I read that I cannot cast an anonymous type to an interface.
Do I have any options here?
A wrapper class was just what the doctor ordered:
ReportServices.GetAllCustomReports().ToList().ForEach(customReport => _customReports.Add(new ReportWrapper(customReport)));
public class ReportWrapper : IReport
{
private Report inner;
public int ID
{
get { return inner.ID; }
set { inner.ID = value; }
}
public string Name
{
get { return inner.Name; }
set { inner.Name = value; }
}
public ReportWrapper(Report obj)
{
inner = obj;
}
}
You will need to wrap this object inside another one that implements the interface, and then you will need to implement it calling the inner object's properties and methods.
For example:
public class ReportWrapper : IReport
{
MyObjectIsLikeReport inner;
public ReportWrapper(MyObjectIsLikeReport obj) {
this.inner = obj;
}
public void ReportMethod(int value) {
this.inner.ReportMethod(value);
}
public int SomeProperty {
get { return this.inner.SomeProperty; }
set { this.inner.SomeProperty = value; }
}
}
To use it, you can do this:
List<IReport> myList = new List<IReport>();
MyObjectIsLikeReport myReport = TheirApi.GetReport();
myList.Add(new ReportWrapper(myReport));
Consider Adapter Design Pattern.
Definition: Convert the interface of a class into another interface
clients expect. Adapter lets classes work together that couldn't
otherwise because of incompatible interfaces.
good reference: http://www.dofactory.com/Patterns/PatternAdapter.aspx
interface IReport
{
void DoSomething();
}
class ReportApdapter : IReport
{
private readonly Report _report;
public ReportApdapter(Report report)
{
_report = report;
}
public void DoSomething()
{
_report.DoSomething();
}
}
class Report
{
public void DoSomething()
{
}
}
//You can use like this.
IReport report = new ReportApdapter(TheirApi.GetReport());

Encapsulating Action<T> and Func<T>?

I'm trying to make a design for some sort of IExecutable interface. I will not get into details, but the point is that I have several Actions that need to be executed from a base class. They may take different parameters (no big deal), and they may/may not return a value.
So far, this is my design:
public abstract class ActionBase
{
// ... snip ...
}
public abstract class ActionWithResultBase<T>: ActionBase
{
public abstract T Execute();
}
public abstract class ActionWithoutResultBase: ActionBase
{
public abstract void Execute();
}
So far, each of my concrete actions need to be a child from either ActionWithResultBase or ActionWithoutResult base, but I really don't like that. If I could move the definition of Execute to ActionBase, considering that the concrete class may or may not return a value, I will have achieved my goal.
Someone told me this could be done with using Func and Action, for which I totally agree, but I can't find a way to have that into one single class so that the caller would know if the action is going to return a value or not.
Brief: I want to do something like:
// Action1.Execute() returns something.
var a = new Action1();
var result = a.Execute();
// Action2.Execute() returns nothing.
var b = new Action2();
b.Execute();
If you want a lightweight solution, then the easiest option would be to write two concrete classes. One will contain a property of type Action and the other a property of type Func<T>:
public class ActionWithResult<T> : ActionBase {
public Func<T> Action { get; set; }
}
public class ActionWithoutResult : ActionBase {
public Action Action { get; set; }
}
Then you can construct the two types like this:
var a1 = new ActionWithResult<int> {
CanExecute = true,
Action = () => {
Console.WriteLine("hello!");
return 10;
}
}
If you don't want to make Action property read/write, then you could pass the action delegate as an argument to the constructor and make the property readonly.
The fact that C# needs two different delegates to represent functions and actions is quite annoying. One workaround that people use is to define a type Unit that represents "no return value" and use it instead of void. Then your type would be just Func<T> and you could use Func<Unit> instead of Action. The Unit type could look like this:
public class Unit {
public static Unit Value { get { return null; } }
}
To create a Func<Unit> value, you'll write:
Func<Unit> f = () => { /* ... */ return Unit.Value; }
The following interfaces should do the trick -- it's essentially copying the Nullable pattern
public interface IActionBase
{
bool HasResult { get; }
void Execute() { }
object Result { get; }
}
public interface IActionBase<T> : IActionBase
{
new T Result { get; }
}
public sealed class ActionWithReturnValue<T> : IActionBase<T>
{
public ActionWithReturnValue(Func<T> action) { _action = action; }
private Func<T> _action;
public bool HasResult { get; private set; }
object IActionBase.Result { get { return this.Result; } }
public T Result { get; private set; }
public void Execute()
{
HasResult = false;
Result = default(T);
try
{
Result = _action();
HasResult = true;
}
catch
{
HasResult = false;
Result = default(T);
}
}
}
public sealed class ActionWithoutReturnValue : IActionBase
{
public bool HasResult { get { return false; } }
object IActionBase.Result { get { return null; } }
public void Execute() { //... }
}
You know that you can ignore the return value of a method right? You don't have to use it.
what about something simple:
public class ActionExecuter
{
private MulticastDelegate del;
public ActionExecuter(MulticastDelegate del)
{
this.del = del;
}
public object Execute(params object[] p)
{
return del.DynamicInvoke(p);
}
}

Unable to perform cast

I need to have a wrapper class that exposes some properties of my entity class called ProfileEntity.
I tried doing it by deriving from this entity and then creating properties that return specific entity properties, but it says I cannot cast from ProfileEntity to ProfileEntityWrapper.
When I try to put the return values of a method that returns a 'ProfileEntity' into the wrapper I get the above error.
How do I create such a wrapper class that is castable?
Example
class ProfileEntityWrapper : ProfileEntity
{
public string Name
{
get
{
return this.ProfileEntityName;
}
}
}
public class Someclass
{
public ProfileEntity SomeMethod()
{
return ProfileEntity; // example of method returning this object
}
}
public class SomeOtherlClass
{
SomeClass sc = new SomeClass();
public void DoSomething()
{
ProfileEntityWrapper ew = (ProfileEntityWrapper)sc.SomeMethod(); // Cannot do this cast!!!
}
}
You cannot cast an object of ProfileEntity to ProfileEntityWrapper.
var entity = new ProfileEntity(); // this object is only of type ProfileEntity
var wrapper = new ProfileEntityWrapper(); // this object can be used as both ProfileEntityWrapper and ProfileEntity
You probably want to return a ProfileEntityWrapper in SomeMethod():
public class Someclass
{
public ProfileEntity SomeMethod()
{
return new ProfileEntityWrapper(); // it's legal to return a ProfileEntity
}
}
No, that is not possible.
To accomplish this problem you can maybe try this one:
public class ProfileEntity
{
public string ProfileEntityName { get; set; }
}
public class ProfileEntityWrapper
{
public ProfileEntityWrapper(ProfileEntity entity)
{
Entity = entity;
}
public ProfileEntity Entity { get; private set; }
public string Name
{
get
{
return Entity.ProfileEntityName;
}
}
}
public class SomeClass
{
public ProfileEntity SomeMethod()
{
// example of method returning this object
ProfileEntity temp = new ProfileEntity();
return temp;
}
}
public class SomeOtherClass
{
SomeClass sc = new SomeClass();
public void DoSomething()
{
//Create a new Wrapper for an existing Entity
ProfileEntityWrapper ew = new ProfileEntityWrapper(sc.SomeMethod());
}
}
If you are allowed to edit the ProfileEntity class, or if the ProfileEntity class is a generated partial class, you could add an interface instead of using a wrapper. You wouldn't need to do any casting with an interface either. Example:
public interface IProfile
{
string Name { get; }
}
public partial class ProfileEntity : IProfile
{
public string Name
{
get
{
return this.ProfileEntityName;
}
}
}
public class SomeClass
{
public ProfileEntity SomeMethod()
{
return ProfileEntity;
}
}
public class SomeOtherClass
{
SomeClass sc = new SomeClass();
public void DoSomething()
{
IProfile ew = sc.SomeMethod();
}
}
The IProfile instance will only provide access to the Name property.
This's no correct code from polymorphism aspect.
If we will take the famous polymorphism example when there're base Shape class and Circle, Polygon and Rectangle classes that extend the Shape class, your code will try to cast some shape into circle and as you understand this's invalid casting operation.
So to make this code work you must be sure that SomeClass.SomeMethod() will return instance of ProfileEntityWrapper or perform type check before the casting, like this:
ProfileEntity temp = sc.SomeMethod();
if(temp is ProfileEntityWrapper)
ProfileEntityWrapper ew = (ProfileEntityWrapper) temp;

Categories

Resources