Variant delegates in variant interfaces. Confused [duplicate] - c#

Earlier I had a good understanding of variance in interfaces. Now I'm a little confused with the variance in delegates in variant interfaces. Methods, properties, indexers, and events can be defined in interfaces. The signature of methods, properties and indexers in the variant interface is direct. And the events are reversed.
I don’t understand why a value-returning method works in a covariant interface, but a similar signature for a delegate does not work. A contravariant delegate that should not return anything works. The same goes for the contravariant interface.
Code below:
namespace ConsoleApp1
{
delegate T MyDelegateReturn<out T>();
delegate void MyDelegateTake<in T>(T t);
interface IMyInterfaceReturn<out T>
{
T MyMethodReturn(); //signature with return value and interface with keyword out - ok
//event MyDelegateReturn<T> MyEventReturn; //delegate signature with return value but is error CS1961
event MyDelegateTake<T> MyEventTake; //delegate signature with take parameter but why it is work?
}
interface IMyInterfaceTake<in T>
{
void MyMethodTake(T t); //signature with take argument and interface with keyword in - ok
//event MyDelegateTake<T> MyEventTake; //delegate signature with take parameter but is error CS1961
event MyDelegateReturn<T> MyEventReturn; //delegate signature with return value but why it is work?
}
class MyClass<T> : IMyInterfaceReturn<T>, IMyInterfaceTake<T>
{
public event MyDelegateTake<T> MyEventTake;
public event MyDelegateReturn<T> MyEventReturn;
public T MyMethodReturn()
{
return default;
}
public void MyMethodTake(T t)
{
}
}
class A
{
}
class B : A
{
}
class Program
{
static void Main(string[] args)
{
B MyMethodReturn()
{
return default;
}
void MyMethodTake(A i)
{
}
MyClass<B> myClass1 = new MyClass<B>();
myClass1.MyEventTake += MyMethodTake;
MyClass<A> myClass2 = new MyClass<A>();
myClass2.MyEventReturn += MyMethodReturn;
}
}
}

The rule is that the types of events must be input-safe. This is the same as method parameters. This makes sense, because when you declare events in interface decelerations, you're essentially declaring a pair of add and remove accessors, that look something like this:
void add_MyEventTake(MyDelegateTake<T> value);
void remove_MyEventTake(MyDelegateTake<T> value);
These will be called when you use += and -= on the event.
So to simplify things, we'll consider methods that accept MyDelegateTake and MyDelegateReturn.
interface IMyInterfaceReturn<out T>
{
T Get();
void add_MyEventTake(MyDelegateTake<T> t);
}
There is a section in the C# spec that describes the rules. You can check out the rules if you want, but I'll try to explain this more intuitively.
At the end of the section, it describes how to interpret "input-safe" and "output-safe" intuitively:
Intuitively, an output-unsafe type is prohibited in an output position, and an input-unsafe type is prohibited in an input position.
A type is output-safe if it is not output-unsafe, and input-safe if it is not input-unsafe.
In IMyInterfaceReturn, T is covariant, so output-safe, and so should only be used in an "output position". I will now show that the parameter MyDelegateTake<T> is indeed an "output position".
Suppose you have an implementation of IMyInterfaceReturn<string> called Foo:
class Foo : IMyInterfaceReturn<string>
{
public void add_MyEventTake(MyDelegateTake<string> t)
{
t(Get());
}
public string Get()
{
return "Something produced by Foo";
}
}
you can use Foo like this:
var foo = new Foo();
foo.add_MyEventTake(str => /* do something with str */);
Wouldn't you agree that str is some sort of "output" of Foo? The above code is really just the following, but in a more indirect way:
var foo = new Foo();
var str = foo.Get();
// do something with str...
Therefore, it follows that T is in an output position, and you can safely do things like assign foo to a variable of type IMyInterfaceReturn<object>.
If add_MyEventTake took a MyDelegateReturn however, add_MyEventTake would be a consumer of T, and T would be in an input position. Foo could be used like this:
var foo = new Foo();
foo.add_MyEventTake(() => "Some Input For Foo!");
// this is just a roundabout way of doing:
foo.add_MyEventTake("Some Input Fo Foo!");
And suppose that Foo were implemented like this:
class Foo : IMyInterfaceReturn<string>
{
private string s;
public void add_MyEventTake(MyDelegateReturn<string> t)
{
s = t();
}
public string Get()
{
return s.ToUpper();
}
}
Then this code would break:
IMyInterfaceReturn<object> foo = new Foo();
foo.add_MyEventTake(() => new object());
foo.Get(); // what would this do? object has no ToUpper!?

Related

Using dynamically generated type for variable declaration and assignment

Following this question, it is possible to create a type and an instance form it dynamically like this:
var type = typeof(AnimalContext<>).MakeGenericType(a.GetType());
var a_Context = Activator.CreateInstance(type);
Great.
However, what I want to do instead of creating an instance of a determined type with Activator.CreateInstance(type);is to use a dynamic created type to declare a variable, and assign an instance to my dynamically created type.
Kind of:
myDynamicallyCreatedType variableName = figuredTypeInstace;
But I cannot use the created type(var type = typeof(AnimalContext<>).MakeGenericType(a.GetType()); for declarations. Is that possible?
Edit:
Short scenario explanation where the need came up. I need to call a method that will be called from a "topManager", this topManager holds the respective instance of the types type1Manager and type2Manager that implement the same base interface IMyInterface method ImplementedMethod.
What I am trying to do, could be solved with ifs, like this:
private int HandleInstance(Type itemType, //other args) {
if (itemType == Type.type1) {
topManagerInstance.manager1Instance.ImplementedMethod(//args):
}
elseif (itemType == Type.type2) {
topManagerInstance.manager2Instance.ImplementedMethod(//args):
}
...not meaningful code
{
But, I was wondering if it could be solved handling types to avoid the ifs, like (caps used to spot the key of the question out, not to shout):
private int HandleInstance(Type itemType, //other args) {
Type managerType = itemType == Type.type1 ? typeof(manager1Type) :
typeof(manager2Type);
Type[] managerTypeArray = { managerType, typeof(int) };
var myDynamicallyCreatedType = typeof(IMyInterface<,>).MakeGenericType(managerTypeArray);
//KEY OF THE QUESTION. THIS IS WHAT I AM ASKING FOR
//assign created variable to dynamic created type to call respective method
myDynamicallyCreatedType variableName = topManagerInstance.type1Manager;
//base type. any type1ManagerType or type2ManagerType to be assigned, as
//they inherit from the same IMyInterface<,>, and the type created is
//generic
variableName.ImplementedMethod(//args):
}
It seems like you're just looking to map an enum value to a function call in a specific implementation. One way to do that is to have a factory class that handles it with a Dictionary used as a map. For example:
Given a setup something like this:
// The enum you use for mapping
public enum Thing
{
Foo,
Bar
}
// The various implementations...
public interface ISomeInterface
{
void SomeMethod();
}
public class Foo : ISomeInterface
{
public void SomeMethod() => Console.WriteLine("Foo method!");
}
public class Bar : ISomeInterface
{
public void SomeMethod() => Console.WriteLine("Bar method!");
}
Now you could have a factory that looks like this:
public class MyThingFactory
{
private Dictionary<Thing, ISomeInterface> _registry;
public MyThingFactory()
{
_registry = new Dictionary<Thing, ISomeInterface>
{
{Thing.Foo, new Foo()},
{Thing.Bar, new Bar()},
};
}
public void RunMethod(Thing thing)
{
if(!_registry.TryGetValue(thing, out var item))
{
throw new ArgumentOutOfRangeException(nameof(thing));
}
item.SomeMethod();
}
}
And call it like this:
// You may want to make this static for performance reasons since you won't recreate
// the dictionary every time
var factory = new MyThingFactory();
factory.RunMethod(Thing.Foo);
factory.RunMethod(Thing.Bar);
//Output:
//Foo method!
//Bar method!

deriving types from an array of individually typed classes

I'm trying to come up with the best way to pass multiple individually typed classes into a method. I won't know beforehand how many individually typed classes will be passed into the method so have started the code off like this...
An Interface
public interface ITypedClass {}
A Typed Class
public class TypedClass<T> : ITypedClass
{
public IEnumerable<T> Output() {}
}
A Method
public static void DoSomething(params ITypedClass[] typedClasses) {}
... and with these run something like the following, where the DoSomething method populates the typed classes with respective values based on the collective of what is passed into the DoSomething method.
var typedClassA = new TypedClass<TypeA>();
var typedClassB = new TypedClass<TypeB>();
...
var typedClassN = new TypedClass<TypeN>();
DoSomething(typedClassA, typedClassB, ... typedClassN etc
var valueA - typedClassA.Output();
var valueB - typedClassB.Output();
...
var valueN - typedClassN.Output();
Unfortunately inside the DoSomething method...
var typedClass = (TypedClass<T>)typedClasses.First();
... the individual values in the typedClasses parameter can't be converted back to TypedClass because the DoSomething method doesn't know what T is in each instance.
Can anyone think of a better way to do this?
The answer seems a little bit obvious with more thought. Had to sleep on it a few nights before the obviousness finally clicked. Don't have DoSomething process the typed input, have TypedClass do it for you and instead have DoSomething split up the work.
New Interface
public interface ITypedClass
{
void Input(object value);
}
New Typed Class
The Input method here handles the conversion from object value to List value
public class TypedClass<T> : ITypedClass
{
public List<T> value;
public void Input(object value) {...}
public IEnumerable<T> Output() => value;
}
New Method
DoSomething now divides up the work...
public static void DoSomething(params ITypedClass[] typedClasses)
{
foreach (var c in typedClasses)
{
c.Input(...);
}
}
Now when calling the following ...
var typedClassN = new TypedClass<TypeN>();
DoSomething(... typedClassN ... );
var valueN = typedClassN.Output();
valueN will have a value and DoSomething can handle a variable amount of typed classes

How to Write Generic Extension Method to Convert Type in C#

I am writing a static guard class/api to validate parameters sent to methods.
Code so far looks like:
public static class Guard
{
public static GuardArgument<T> Ensure<T>(T value, string argumentName)
{
return new GuardArgument<T>(value, argumentName);
}
public static T Value<T>(this GuardArgument<T> guardArgument)
{
return guardArgument.Value;
}
// Example extension method
public static GuardArgument<T> IsNotNull<T>(this GuardArgument<T> guardArgument, string errorMessage)
{
if (guardArgument.Value == null)
{
throw new ArgumentNullException(guardArgument.Name, errorMessage);
}
return guardArgument;
}
}
It can be used as so:
public void Test(IFoo foo) {
Guard.Ensure(foo, "foo").IsNotNull();
}
Circumstances now require that I need to cast to concrete types from a supplied interface. Don't ask why, I just need to!
I want to add an As extension method to GuardArgument to do this, something like:
public static GuardArgument<TOut> As<TOut, TIn>(this GuardArgument<TIn> guardArgument, Type type)
where TOut : class
{
// Check cast is OK, otherwise throw exception
return new GuardArgument<TOut>(guardArgument.Value as TOut, guardArgument.Name);
}
I don't much like the syntax though. I want to be able to use the class as follows:
Foo foo = Guard.Ensure(foo, "foo")
.As(typeof(Foo))
.IsNotNull()
.Value();
I'm not sure how to write the extension method to allow this syntax though. I realise I can use the existing fluent API as:
Foo foo = Guard.Ensure(foo as Foo, "foo")
.IsNotNull()
.Value();
but I don't like this from a readability perspective.
You can get this syntax:
Foo foo = Guard.Ensure(foo, "foo")
.As<Foo>()
.IsNotNull()
.Value();
The trick is to ditch the TIn type param. It's not used in the As() method and bloats the API when type inference can't be used due to TOut. To be able to do that without getting As() suggested on all types you have to implement a new, non-generic interface for your GuardArgument<> class:
interface IGuardArgument
{
object Value { get; }
strign Name { get; }
}
public class GuardArgument<T> : IGuardArgument
{
// Explicit implementation to hide this property from
// intellisense.
object IGuardArgument.Value { get { return Value; }
// Rest of class here, including public properties Value and Name.
}
Now you can write the As() method with only one generic param:
public static GuardArgument<TOut> As<TOut>(this IGuardArgument guardArgument)
where TOut : class
{
// Check cast is OK, otherwise throw exception
return new GuardArgument<TOut>(guardArgument.Value as TOut, guardArgument.Name);
}
Introduce an IGuardArgument interface which GuardArgument{T} implements. Then you can remove TIn from the As extension method and remove the Type parameter.
Signature:
public static GuardArgument<TOut> As(this IGuardArgument guardArgument);
Usage:
Guard.Ensure(foo, "foo").As<Foo>().IsNotNull()

How to pass a Func<T> without knowing the scope of T?

It may not be possible, but I am hoping it is!
I have a method which has scope of a generic type, and instansiates a List<Func<GenericType>>. I then have another method which recieves a List<Func<T>>. I can't have any knowledge of T in this method.
Example Code
public void PassFuncs<Item>()
{
List<Func<Item>> funcs = new List<Func<Item>>();
RecieveFuncs(funcs);
}
public void RecieveFuncs(List<Func<object>> funcs)
{
//Do some stuff with funcs
}
I was wishing that it would be as easy as using object in place of T and it would be as easy of that. Of course, T isn't an object, it's a Type and therefore I can't interchange them. Any suggestions or is this impossible?
You can make your method generic:
public void RecieveFuncs<T>(List<Func<T>> funcs)
{
//Do some stuff with funcs
}
To call it, you can either declare T explicitly
public void PassFuncs<Item>()
{
List<Func<Item>> funcs = new List<Func<Item>>();
RecieveFuncs<Item>(funcs);
}
or let the type inference magic do its work and keep the call as it is:
public void PassFuncs<Item>()
{
List<Func<Item>> funcs = new List<Func<Item>>();
RecieveFuncs(funcs); // C# automatically infers T = Item
}
If you can't make RecieveFuncs generic for some reason, you could use:
public void PassFuncs<TItem>()
where TItem:class
{
List<Func<TItem>> funcs = new List<Func<TItem>>();
RecieveFuncs(funcs);
}
public void RecieveFuncs(IEnumerable<Func<object>> funcs)
{
//Do some stuff with funcs
}
This requires a generic constraint to reference types for TItem, and needs a co-variant interface like IEnumerable<T> instead of List<T> on the receiving side. If you really want to receive a List<Func<object>> you can create a new list with List<Func<object>>(funcs).
If you know that Item is a reference type, you can use variance of each function (but not of the list):
public void PassFuncs<Item>() where Item : class
{
List<Func<Item>> funcs = new List<Func<Item>>();
var tmp = funcs.ConvertAll(func => (Func<object>)func);
RecieveFuncs(tmp);
}
This creates a new list, but uses the original functions. If that is not possible, you'll need to add an intermediate function:
public void PassFuncs<Item>()
{
List<Func<Item>> funcs = new List<Func<Item>>();
var tmp = funcs.ConvertAll<Func<object>>(func => () => func());
RecieveFuncs(tmp);
}
You could "cast" the Func<Item> to Func<object>, like this
public delegate object Func();
public void PassFuncs<Item>()
{
List<Func<Item>> funcs = new List<Func<Item>>();
RecieveFuncs(funcs.Select<Func<Item>, Func<object>>(f => () => (object)f())
.ToList());
}
public void RecieveFuncs(List<Func<object>> funcs)
{
//Do some stuff with funcs
}
This will work both for reference and value types, although it will box for the value types. If you use only reference types, use #CodesInChaos answer.

Can a multicast delegate in C# 4.0 be created from some sort of collection of method names?

I'm writing a simple game in XNA and I've faced a problem with delegates. I use them to represent physics in the game, e.g.:
public delegate void PhysicsLaw(World world);
//for gravitation
static public void BallLawForGravity(World world)
{
if (world.ball.position.Y != world.zeroLevel)
//v(t) = v0 + sqrt(c * (h - zeroLevel))
world.ball.speed.Y += (float)Math.Sqrt(0.019 * (world.zeroLevel - world.ball.position.Y));
}
And I want to create multicast delegates for different objects/circumstances consisting from many methods such as BallLawForGravity(), but I can do it only like this:
processingList = BallLawForBounce;
processingList += BallLawForAirFriction;
...
processingList += BallLawForGravity;
Obviously, it doesn't look good. Is there any standard way to create a multicast delegate from collection of method names?
Use the static method Delegate.Combine Method (Delegate[]) for such tasks.
PhysicsLaw[] delegates = new PhysicsLaw[] {
new PhysicsLaw( PhysicsLaw ),
new PhysicsLaw( BallLawForAirFriction )
};
PhysicsLaw chained = (PhysicsLaw) Delegate.Combine( delegates );
chained(world);
More examples.
Update
You can use the creating delegate via Reflection for this but I don't recommend it, because it's very slow technic.
Let's say you've declared
public delegate void foo(int x);
public static void foo1(int x) { }
public static void foo2(int x) { }
public static void foo3(int x) { }
Now you can combine them directly with Delegate.Combine if you don't mind typing the delegate name twice:
foo multicast = (foo)Delegate.Combine(new foo[] { foo1, foo2, foo3 });
Or you can write a generic function to combine them if you don't mind typing the delegate name once:
public static T Combine<T>(params T[] del) where T : class
{
return (T)(object)Delegate.Combine((Delegate[])(object[])del);
}
foo multicast2 = Combine<foo>(foo1, foo2, foo3);
Or you can write a non-generic function to combine them if you don't want to type the delegate name at all:
public static foo Combine(params foo[] del)
{
return (foo)Delegate.Combine(del);
}
foo multicast3 = Combine(foo1, foo2, foo3);

Categories

Resources