I have this scenario:
private MyResponse MakeTransaction<T>(T data)
{
TransactionData transactionData = new TransactionData()
{
number = data.Number
}
if(req is NewPayoutData) {
transactionData.New = data.New;
}
....
}
I call this method like this:
public MyResponse Payment(PayoutData data)
{
return MakeTransaction(data);
}
public MyResponse NewPayment(NewPayoutData data)
{
return MakeTransaction(data);
}
The problem is that 'Number' property exists in both types but the 'New' property exists only in 'NewPayment' Type.
How can I overcome this problem?
Thanks.
The best you're going to get with generics is to constrain T to be a common interface or base class that has the Number property. However this leaves out the setting of the New property which is still based on type checking. Assuming an interface it might look like:
public interface IPayout
{
int Number { get; }
}
public class PayoutData : IPayout { ... }
public class NewPayoutData : IPayout { ... }
private MyResponse MakeTransaction<T>(T data) where T: IPayout
{
TransactionData transactionData = new TransactionData
{
number = data.Number // now works
};
// type checking still required :-(
if(data is NewPayoutData)
{
transactionData.New = true;
}
...
}
The type checking sort of defeats the purpose of generics. If you only have the two types a generic method is probably not the best way to go. I'd consider method overloading instead--especially since NewPayoutData looks to just be a marker type:
private MyResponse MakeTransaction(PayoutData data)
{
TransactionData transactionData = new TransactionData
{
number = data.Number
};
...
}
private MyResponse MakeTransaction(NewPayoutData data)
{
TransactionData transactionData = new TransactionData
{
number = data.Number,
New = true
};
...
}
If they have an inheritence relationship, you could still have a single method that checks for the subclass:
public class PayoutData
{
public int Number { get; set; }
}
public class NewPayoutData : PayoutData
{
}
private MyResponse MakeTransaction(PayoutData data)
{
TransactionData transactionData = new TransactionData
{
number = data.Number
};
// type checking
if(data is NewPayoutData)
{
transactionData.New = true;
}
...
}
My preferred method would be overloading as I think it's more explicit.
You could specifically cast transactionData to the required type. Better would probably be to make helper methods that deal with (strongly typed) functionality and call those from MakeTransaction.
I'm not entirely sure of your inheritance model, nor what you actually return in MakeTransaction, so I could be off base.
Related
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.
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);
}
Assuming there's an enumeration defined as follows:
public enum Beep
{
HeyHo,
LetsGo
}
I wonder if it's possible to improve the following property:
public Dictionary<Beep, String> Stuff{ get; set; }
...
String content = Stuff[Beep.HeyHo]
because the way it's right now, I retrieve the dictionary and then pick out the element I need. I wonder if it's (a) possible at all and if so (b) recommended to create something like this pseudo-code.
public String Stuff{ get<Beep>; set<Beep>; }
...
String content = Stuff[Beep.HeyHo]
You can apply an indexer to your class.
It is recommended, as it improves encapsulation. For example, it's perfectly possible using the original code to replace the Dictionary entirely with a different dictionary - which is probable not desirable.
public class MyClass
{
// Note that dictionary is now private.
private Dictionary<Beep, String> Stuff { get; set; }
public String this[Beep beep]
{
get
{
// This indexer is very simple, and just returns or sets
// the corresponding element from the internal dictionary.
return this.Stuff[beep];
}
set
{
this.Stuff[beep] = value;
}
}
// Note that you might want Add and Remove methods as well - depends on
// how you want to use the class. Will client-code add and remove elements,
// or will they be, e.g., pulled from a database?
}
Usage:
MyClass myClass = new MyClass();
string myValue = myClass[Beep.LetsGo];
You can also use an indexer.
class MyClass
{
private readonly Dictionary<Beep, string> _stuff = new Dictionary<Beep, string>();
public string this[Beep beep]
{
get { return _stuff[beep]; }
set { _stuff[beep] = value; }
}
}
Now, instead of calling
var obj = new MyClass();
string result = obj.Stuff[Beep.HeyHo];
You can call
var obj = new MyClass();
string result = obj[Beep.HeyHo];
Indexers work much like properties but have at least one argument used as index. You can have only one indexer per class, however you can create different overloads of it. The same overloading rules apply as for methods.
Something like this using Indexer
public class Stuff
{
public Dictionary<Beep, String> _stuff { get; set; }
public enum Beep
{
HeyHo,
LetsGo
}
public Stuff()
{
_stuff = new Dictionary<Beep, string>();
// add item
_stuff[Beep.HeyHo] = "response 1";
_stuff[Beep.LetsGo] = "response 2";
}
public string this[Beep beep]
{
get { return _stuff[beep]; }
}
}
Sample Usage :
public static class Program
{
private static void Main()
{
Stuff stuff = new Stuff();
string response;
response = stuff[Stuff.Beep.HeyHo]; // response 1
response = stuff[Stuff.Beep.LetsGo]; // response 2
}
}
Maybe I'm overworked, but this isn't compiling (CS0411). Why?
interface ISignatur<T>
{
Type Type { get; }
}
interface IAccess<S, T> where S : ISignatur<T>
{
S Signature { get; }
T Value { get; set; }
}
class Signatur : ISignatur<bool>
{
public Type Type
{
get { return typeof(bool); }
}
}
class ServiceGate
{
public IAccess<S, T> Get<S, T>(S sig) where S : ISignatur<T>
{
throw new NotImplementedException();
}
}
static class Test
{
static void Main()
{
ServiceGate service = new ServiceGate();
var access = service.Get(new Signatur()); // CS4011 error
}
}
Anyone an idea why not? Or how to solve?
Get<S, T> takes two type arguments. When you call service.Get(new Signatur()); how does the compiler know what T is? You'll have to pass it explicitly or change something else about your type hierarchies. Passing it explicitly would look like:
service.Get<Signatur, bool>(new Signatur());
Kirk's answer is right on. As a rule, you're not going to have any luck with type inference when your method signature has fewer types of parameters than it has generic type parameters.
In your particular case, it seems you could possibly move the T type parameter to the class level and then get type inference on your Get method:
class ServiceGate<T>
{
public IAccess<S, T> Get<S>(S sig) where S : ISignatur<T>
{
throw new NotImplementedException();
}
}
Then the code you posted with the CS0411 error could be rewritten as:
static void Main()
{
// Notice: a bit more cumbersome to write here...
ServiceGate<SomeType> service = new ServiceGate<SomeType>();
// ...but at least you get type inference here.
IAccess<Signatur, SomeType> access = service.Get(new Signatur());
}
Now my aim was to have one pair with an base type and a type definition (Requirement A). For the type definition I want to use inheritance (Requirement B). The use should be possible, without explicite knowledge over the base type (Requirement C).
After I know now that the gernic constraints are not used for solving the generic return type, I experimented a little bit:
Ok let's introducte Get2:
class ServiceGate
{
public IAccess<C, T> Get1<C, T>(C control) where C : ISignatur<T>
{
throw new NotImplementedException();
}
public IAccess<ISignatur<T>, T> Get2<T>(ISignatur<T> control)
{
throw new NotImplementedException();
}
}
class Test
{
static void Main()
{
ServiceGate service = new ServiceGate();
//var bla1 = service.Get1(new Signatur()); // CS0411
var bla = service.Get2(new Signatur()); // Works
}
}
Fine, but this solution reaches not requriement B.
Next try:
class ServiceGate
{
public IAccess<C, T> Get3<C, T>(C control, ISignatur<T> iControl) where C : ISignatur<T>
{
throw new NotImplementedException();
}
}
class Test
{
static void Main()
{
ServiceGate service = new ServiceGate();
//var bla1 = service.Get1(new Signatur()); // CS0411
var bla = service.Get2(new Signatur()); // Works
var c = new Signatur();
var bla3 = service.Get3(c, c); // Works!!
}
}
Nice! Now the compiler can infer the generic return types. But i don't like it.
Other try:
class IC<A, B>
{
public IC(A a, B b)
{
Value1 = a;
Value2 = b;
}
public A Value1 { get; set; }
public B Value2 { get; set; }
}
class Signatur : ISignatur<bool>
{
public string Test { get; set; }
public IC<Signatur, ISignatur<bool>> Get()
{
return new IC<Signatur, ISignatur<bool>>(this, this);
}
}
class ServiceGate
{
public IAccess<C, T> Get4<C, T>(IC<C, ISignatur<T>> control) where C : ISignatur<T>
{
throw new NotImplementedException();
}
}
class Test
{
static void Main()
{
ServiceGate service = new ServiceGate();
//var bla1 = service.Get1(new Signatur()); // CS0411
var bla = service.Get2(new Signatur()); // Works
var c = new Signatur();
var bla3 = service.Get3(c, c); // Works!!
var bla4 = service.Get4((new Signatur()).Get()); // Better...
}
}
My final solution is to have something like ISignature<B, C>, where B ist the base type and C the definition...
As I mentioned in my comment, I think the reason why this doesn't work is because the compiler can't infer types based on generic constraints.
Below is an alternative implementation that will compile. I've revised the IAccess interface to only have the T generic type parameter.
interface ISignatur<T>
{
Type Type { get; }
}
interface IAccess<T>
{
ISignatur<T> Signature { get; }
T Value { get; set; }
}
class Signatur : ISignatur<bool>
{
public Type Type
{
get { return typeof(bool); }
}
}
class ServiceGate
{
public IAccess<T> Get<T>(ISignatur<T> sig)
{
throw new NotImplementedException();
}
}
static class Test
{
static void Main()
{
ServiceGate service = new ServiceGate();
var access = service.Get(new Signatur());
}
}
I wanted to make a simple and understandable example
if you call a method like this, your client will not know return type
var interestPoints = Mediator.Handle(new InterestPointTypeRequest
{
LanguageCode = request.LanguageCode,
AgentId = request.AgentId,
InterestPointId = request.InterestPointId,
});
Then you should say to compiler i know the return type is List<InterestPointTypeMap>
var interestPoints = Mediator.Handle<List<InterestPointTypeMap>>(new InterestPointTypeRequest
{
LanguageCode = request.LanguageCode,
AgentId = request.AgentId,
InterestPointId = request.InterestPointId,
InterestPointTypeId = request.InterestPointTypeId
});
the compiler will no longer be mad at you for knowing the return type
I received this error because I had made a mistake in the definition of my method. I had declared the method to accept a generic type (notice the "T" after the method name):
protected int InsertRecord<T>(CoasterModel model, IDbConnection con)
However, when I called the method, I did not use the type which, in my case, was the correct usage:
int count = InsertRecord(databaseToMigrateFrom, con);
I just removed the generic casting and it worked.
For those who are wondering why this works in Java but not C#, consider what happens if some doof wrote this class:
public class Trololol : ISignatur<bool>, ISignatur<int>{
Type ISignatur<bool>.Type => typeof(bool);
Type ISignatur<int>.Type => typeof(int);
}
How is the compiler supposed to resolve var access = service.Get(new Trololol())? Both int and bool are valid.
The reason this implicit resolution works in Java likely has to do with Erasure and how Java will throw a fit if you try to implement an interface with two or more different type arguments. Such a class is simply not allowed in Java, but is just fine in C#.
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);
}
}