Overriding async method properly in C# - c#

I have a base class that defines an abstract method that returns a Task.
public abstract class BaseClass
{
public abstract Task DoSomething();
}
I can make a class that implements the abstract method in these two different ways.
public class Example1 : BaseClass
{
public override Task DoSomething()
{
return Task.CompletedTask;
}
}
or like this
public class Example2 : BaseClass
{
public override async Task DoSomething()
{
}
}
Notice that the first returns a completed task, the second includes the async keyword and doesn't have a return statement. Is there any difference between the two?

There is significant difference in the code that gets generated. By merely adding the async keyword the method gets compiled very differently.
Here's effectively what the compiler produces:
public class Example2 : BaseClass
{
private struct DoSomethingStateMachine : IAsyncStateMachine
{
public int _state;
public AsyncTaskMethodBuilder _builder;
private void MoveNext()
{
try
{
}
catch (Exception exception)
{
_state = -2;
_builder.SetException(exception);
return;
}
_state = -2;
_builder.SetResult();
}
void IAsyncStateMachine.MoveNext()
{
this.MoveNext();
}
private void SetStateMachine(IAsyncStateMachine stateMachine)
{
_builder.SetStateMachine(stateMachine);
}
void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
{
this.SetStateMachine(stateMachine);
}
}
public override Task DoSomething()
{
DoSomethingStateMachine stateMachine = default(DoSomethingStateMachine);
stateMachine._builder = AsyncTaskMethodBuilder.Create();
stateMachine._state = -1;
AsyncTaskMethodBuilder _builder = stateMachine._builder;
_builder.Start(ref stateMachine);
return stateMachine._builder.Task;
}
}

Related

Pass more-derived type (via 'this') in less-derived method to overloaded method

Simple hierarchy, 3 levels and with a shared/single dependency to a class with overloaded methods that differ only by type signature:
When viewed in a debugger, the type of 'this' in Derived.Bar is the instantiated/concrete Double-Derived.
The below works as expected ONLY because of the (dynamic) cast. Remove it and you'll see that the overload resolution uses the calling class rather than the concrete class.
Curious if there's a 'purer' way of it working as expected without the performance hit of DLR (or some other reflection-based alternative):
public class PolymorphicConsumer
{
public void Foo(Base caller)
{
Console.WriteLine("Its all about the base.");
}
public void Foo(Derived caller)
{
Console.WriteLine("Its all about the Derived.");
}
public void Foo(DoubleDerived caller)
{
Console.WriteLine("Its all about the Double-Derived.");
}
}
public abstract class Base
{
protected PolymorphicConsumer _dep;
public Base (PolymorphicConsumer dep)
{
_dep = dep;
}
public virtual void Bar()
{
// No impl.
}
}
public class Derived : Base
{
public Derived(PolymorphicConsumer dep):base(dep)
{ }
public override void Bar()
{
_dep.Foo((dynamic)this);
}
}
public class DoubleDerived : Derived
{
public DoubleDerived(PolymorphicConsumer dep):base(dep)
{ }
}
class Program
{
static void Main(string[] args)
{
var dd = new DoubleDerived(new PolymorphicConsumer());
dd.Bar();
Console.ReadKey();
}
}

Activator.CreateInstance with an Interface parameter

I have a Reflection method, which I load an Instance of an class with a specific name. I have an abstract class which define my classes. Now I also have an interface in the constructor of this abstract class. It's a bit hard to explain and I'm not sure if it's a correct way to implement my problem. But here is my source code, which should explain the most:
Program:
private static void Main(string[] args)
{
int result;
if (args.Length > 0)
{
string jobName = args[0];
Type[] types = Assembly.GetAssembly(typeof(Task)).GetTypes();
foreach (Type type in types)
{
if (type.Name == jobName)
{
//Here is my problem. I need my Interface instead of null
_job = (Task)Activator.CreateInstance(type, null);
}
}
if (_job != null)
{
result = _job.Run(args);
}
}
//Dispose the Job
_job = null;
}
Task:
public abstract class Task
{
public IArgument Argument;
protected Task(IArgument argument)
{
Argument = argument;
}
public int Run(string[] args)
{
int result;
if (SetArguments(args))
{
result = Work();
}
return result;
}
protected abstract int Work();
Interface:
public interface IArgument
{
bool SetArguments(string[] args);
}
Now I can create an "Task" class and an "Argument" class:
public class ImportArgument : IArgument
{
public bool SetArguments(string[] args)
{
return true;
}
}
public class ImportTask : Task
{
protected override int Work()
{
return 1;
}
public ImportTask(IArgument argument) : base(argument)
{
Argument = new ArticleImportArgument();
}
}
What do you guys think. Is there a way where I can create an Instance of the task class with an Interface in the constructor? Is there another way to solve this problem? I could also create an abstract method in my Task class where I have to implement my Interface, but I think the constructor would be a better way.

Force override method if another method is overriden

Is there a way to force the override of a virtual method if another method is overriden?
public class BaseClass
{
protected virtual void A()
{
// a default action called first
}
protected virtual void B()
{
// a default action called second that,
// if A was overriden, makes no sense
}
}
EDIT
Thanks a lot for the Answers. It's very interresting to see how this could be achieved, but for my explicit case it's not critically important.
Also, i forgot to mention how those Methods would be used: (in BaseClass)
pulbic bool EditEntity(Guid id)
{
A();
// Some code that edits Entites
B();
}
No, you cannot. But this makes me think how could you achieve the same concept?
The best idea I came up with was declaring an interface which had the package of methods to override.
public interface IMyOverridablePackage
{
void A_Override();
void B_Override();
}
Then give the base class a protected method where the child class can explicitly override the set of methods.
protected void SetOverride(IMyOverridablePackage overridablePackage)
{
_overridablePackage = overridablePackage;
}
So then here's two classes, one which does and one which does not override the set of methods:
public class NotOverriding : MyBaseClass
{
}
public sealed class Overriding : MyBaseClass, IMyOverridablePackage
{
public Overriding()
{
SetOverride(this);
}
void IMyOverridablePackage.A_Override()
{
Console.WriteLine("Overriding.A_Override");
}
void IMyOverridablePackage.B_Override()
{
Console.WriteLine("Overriding.B_Override");
}
}
And the implementation of the base class:
public abstract class MyBaseClass
{
private IMyOverridablePackage _overridablePackage;
public void A()
{
_overridablePackage.A_Override();
}
public void B()
{
_overridablePackage.B_Override();
}
private class MyDefaultPackage : IMyOverridablePackage
{
private readonly MyBaseClass _myBaseClass;
internal MyDefaultPackage(MyBaseClass myBaseClass)
{
_myBaseClass = myBaseClass;
}
void IMyOverridablePackage.A_Override()
{
_myBaseClass.A_Impl();
}
void IMyOverridablePackage.B_Override()
{
_myBaseClass.B_Impl();
}
}
protected MyBaseClass()
{
_overridablePackage = new MyDefaultPackage(this);
}
private void A_Impl()
{
Console.WriteLine("MyBaseClass.A_Impl");
}
private void B_Impl()
{
Console.WriteLine("MyBaseClass.B_Impl");
}
protected void SetOverride(IMyOverridablePackage overridablePackage)
{
_overridablePackage = overridablePackage;
}
}
This does achieve the goal, but of course you have to ask 'how much to I want it?' Is it worth the extra code?
Here's a working dotnetfiddle: https://dotnetfiddle.net/xmPn20
Maybe you cannot force it via compiler errors, but you could write a test which asserts that the methods are in sync via some attributes. It would also be visible that there is some dependency.
A crude example would be something like this:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class VersionAttribute : Attribute
{
public VersionAttribute(string version)
{
Version = version;
}
public string Version { get; set; }
}
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class DependentAttribute : Attribute
{
public string DependentOnMethod { get; set; }
public string DependentOnVersion { get; set; }
}
[Dependent(DependentOnMethod = "OtherMethod", DependentOnVersion = "1")]
public static void FirstMethod()
{
}
[Version("1")]
public static void OtherMethod()
{
}
And the test that asserts the version numbers:
[Test]
public void TestVersions()
{
foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
{
foreach (var method in type.GetMethods())
{
foreach (var customAttribute in method.GetCustomAttributes())
{
var dependent = customAttribute as DependentAttribute;
if (dependent != null)
{
var methodInfo = type.GetMethod(dependent.DependentOnMethod);
Assert.That(methodInfo, Is.Not.Null, "Dependent method not found");
VersionAttribute version = methodInfo.GetCustomAttributes().OfType<VersionAttribute>().FirstOrDefault();
Assert.That(version, Is.Not.Null, "No version attribute on dependent method");
Assert.That(dependent.DependentOnVersion, Is.EqualTo(version.Version));
}
}
}
}
}
thus, if you update one of your methods you would need to update the version number of either the Version attribute or the Dependent attribute. Hopefully better than nothing.
You may change your design :
public abstract class BaseClass
{
protected abstract void A();
}
public class BaseClassEx
{
protected sealed override void A()
{
// action Calling B
}
protected virtual void B()
{
// a default action called second
}
}
In the case of Equals (actually both Equals overloads, concrete type and object) and GetHashCode, Resharper includes a rule that shows a warning in its IntelliSense whenever you forget to implement one of these.
You could enforce it in your code with a runtime check in the constructor of the base class:
public class Base
{
public Base()
{
var baseA = typeof (Base).GetRuntimeMethod("MethodA", new Type[0]);
var baseB = typeof (Base).GetRuntimeMethod("MethodB", new Type[0]);
var derivedA = GetType().GetRuntimeMethod("MethodA", new Type[0]);
var derivedB = GetType().GetRuntimeMethod("MethodB", new Type[0]);
if (baseA.DeclaringType == derivedA.DeclaringType ^
baseB.DeclaringType == derivedB.DeclaringType)
throw new InvalidOperationException("You must override MethodA and MethodB together.");
}
public virtual string MethodA() { return "Hello"; }
public virtual int MethodB() { return 123; }
}

Wrapping methods with different signatures, pre-and-post-invocation

How to avoid a pair of repetitive lines before and after invocations in sample below ?
Details: This is compileable mock of what is real larger code. Generally it is a layer of proxy classes containing service clients with variety of APIs. The repetitive part is pre- and post- invocation for every method of every client. Unfortunately there is no single signature for all possible methods, the pre- and post- parts need a pointer to client's channel and context.
Is it possible to apply something advanced like AOP, Generics, Delegates, Attributes etc. ? Thank you
using System;
namespace ConsoleApplication
{
class ClassServiceClient: IDisposable
{
public Object channel()
{
return "something";
}
public Object context()
{
return "something other";
}
}
class ClassA : ClassServiceClient
{
public Object methodA()
{
return "something other";
}
}
class ClassB : ClassServiceClient
{
public void methodB(string param)
{
return;
}
}
class ClassAProxy
{
public Object methodA()
{
using (ClassA client = new ClassA())
{
Program.preparation(client.channel()); //<---- repetitive part
Object result = client.methodA();
Program.postinvocation(client.context());//<---- repetitive part
return result;
}
}
}
class ClassBProxy
{
public void methodB(string param)
{
using (ClassB client = new ClassB())
{
Program.preparation(client.channel()); //<---- repetitive part
client.methodB(param);
Program.postinvocation(client.context());//<---- repetitive part
return;
}
}
}
class Program
{
public static void preparation(Object channel)
{
// Do something with channel
}
public static void postinvocation(Object context)
{
// Do something with context
}
static void Main(string[] args)
{
}
}
}
If you can use a common base class, you can easily use a public sealed method that does the invocation and a protected abstract method that does the logic, e.g.
class ProxyBase{
public void Method(params object[] args){
PreConditions();
Invoke(args);
PostConditions();
}
protected abstract void Invoke(object[] args);
}
class ClassAProxy{
protected override void Invoke(object[] args){
client.Method(args[0]);
}
}
You can achieve similar results functionally by declaring a InvocationHandler in your Program class that takes an action:
class Program{
public static void Invoke(object[] args, Action action){
PreConditions();
action();
PostConditions();
}
}
class ClassAProxy{
public void MethodA(int i){
Program.Invoke(() => client.Something(i));
}
}

How to have an abstract method return an abstract type with concrete implementations?

I have three classes that will each return a slightly different result.
// interfact to a king
public interface IKing{
public Result Get();
}
// main abstract class
public abstract class King:IKing{
public abstract Result Get();
}
// main abstract result
public abstract class Result{
public int Type {get;set;}
}
// KingA result
public class ResultA:Result{
...
}
// KingB result
public class ResultB:Result{
...
}
// concrete implementations
public class KingA:King{
public override ResultA Get(){
return new ResultA;
}
}
public class KingB:King{
public override ResultB Get(){
return new ResultB
}
}
This will not work since the King overriden method of Get is expecting the Result class and will not accept its children ResultA and ResultB.
Is there a better approach I can take?
The usual approach is to use generics.
public interface IKing<T> where T:Result{
T Get();
}
public class King<T> : IKing<T>
public abstract T Get();
}
public class KingA : King<ResultB> {
public override ResultA Get(){
return new ResultA();
}
}
public class KingB : King<ResultB> {
public override ResultB Get(){
return new ResultB();
}
}
Edit: fixed syntax.
It will help if you use code that compiles. Your 'concrete implementations' are bogus, it looks like you mixed the concepts of class and method. There is otherwise no design problem here. For example:
public class KingA : King {
public override Result Get() {
return new ResultA();
}
}
I think there's some syntax confusion here -- if I captured your intent correctly, this works fine:
// interface to a king
public interface IKing
{
Result Get();
}
// main abstract class
public abstract class King : IKing
{
public abstract Result Get();
}
// main abstract result
public abstract class Result
{
private int _Type;
public int Type { get { return _Type; } set { _Type = value; } }
}
// KingA result
public class ResultA : Result
{
}
// KingB result
public class ResultB : Result
{
}
// concrete implementations
public class KingA : King
{
public override Result Get()
{
return new ResultA();
}
}
public class KingB : King
{
public override Result Get()
{
return new ResultB();
}
}
class Program
{
static void Main(string[] args)
{
IKing ka = new KingA();
IKing kb = new KingB();
Result ra = ka.Get();
Result rb = kb.Get();
if (ra is ResultA)
{
Console.WriteLine("A ok!");
}
if (rb is ResultB)
{
Console.WriteLine("B ok!");
}
}
}
(edited for formatting)
You should be able to explicitly cast ResultA and ResultB as Result in the implementations of Get (I'm assuming that's what the "concrete implementations" are intended to be).

Categories