Is there some way that this can work?
class A
{
public virtual string Greet() { return "Hello"; }
}
class B : A
{
public override string Greet() { return "Hola"; }
}
class C : A
{
public override string Greet() { return "Привет"; }
}
class Greeting<T>
{
List<T> list;
public Greeting(List<T> list)
{
this.list = new List<T>();
this.list.AddRange(list);
}
public void Show()
{
foreach (T el in list)
el.Greet(); // 'T' does not contain a definition for 'Greet'
}
}
class Program
{
static void Main(string[] args)
{
List<A> list = new List<A>() { new A(), new B(), new C() };
Greeting<A> g = new Greeting<A>(list);
g.Show();
}
}
I know that in this case I should write List<Shop> list(in Greeting class) and don't use generic class...but I need this implementation to work
You need to add a constraint on T, without it, the compiler has no way of knowing you will only pass objects which derive from A and the method isn't available:
class Greeting<T> where T : A
{
List<T> list;
public Greeting(List<T> list)
{
this.list = new List<T>();
this.list.AddRange(list);
}
public void Show()
{
foreach (T el in list)
el.Greet(); // 'T' does not contain a definition for 'Greet'
}
}
Related
Consider:
class BasicType
{
public BasicType() { }
public T Save<T>() where T : BasicType
{
BasicType b = DataContext.Save(this); //Returns a BasicType
return (T)Activator.CreateInstance(typeof(T), b);
}
}
class DerivedType : BasicType
{
public DerivedType(BasicType b) { }
}
public static void Main()
{
DerivedType d = new DerivedType();
d = d.Save<DerivedType>();
}
This works, but being forced to specify the type each time I call Save is a drag.
Is there some way to change the BasicType.Save method such that it will always return an instance of the actual type (derived or base) of the instance on which Save is being called?
Generics are not needed in this case.
I think this should be enough:
public BasicType Save()
{
BasicType b = DataContext.Save(this); //Returns a BasicType
return (BasicType)Activator.CreateInstance(this.GetType(), b);
}
Anyway you should be carefull with this as the inherited classes may not have the expected constructor.
Is better to override the save method, or at least the specific part.
You could change your definition of BasicType so that you're forced to provide the type of T at the point of inheritance.
Something like this:
class BasicType<T> where T : BasicType<T>, new()
{
public BasicType() { }
public T Save()
{
T b = new T();
return (T)Activator.CreateInstance(typeof(T), b);
}
}
class DerivedType : BasicType<DerivedType>
{
public DerivedType() { }
}
class Program
{
static void Main(string[] args)
{
DerivedType d = new DerivedType();
d = d.Save();
}
}
Something like this.
class BasicType
{
public BasicType()
{
}
protected virtual T Save<T>()
{
BasicType b = DataContext.Save(this); //Returns a BasicType
return (T)Activator.CreateInstance(typeof(T), b);
}
}
class DerivedType : BasicType
{
public DerivedType(BasicType b)
{
}
public DerivedType Save()
{
return base.Save<DerivedType>();
}
}
public static void Main()
{
DerivedType d = new DerivedType(new BasicType());
d = d.Save();
}
I have a C# Converter method which convers generic lists with the use of reflection.
The problem occurs when I try to call the SetValue method of the Item's property, it throws the following inner exception (ArgumentOutOfRangeException):
Index was out of range. Must be
non-negative and less than the size of the collection. Parameter name:
index.
Here is my code:
internal class Program
{
private static void Main()
{
List<ClassA> classA = new List<ClassA>();
classA.Add(new ClassA { Data = "value1" });
classA.Add(new ClassA { Data = "value2" });
List<ClassB> classB = Converter<List<ClassA>, List<ClassB>>(classA);
}
public static TOut Converter<TIn, TOut>(TIn request)
{
var response = Activator.CreateInstance<TOut>();
PropertyInfo propertyA = typeof(TIn).GetProperty("Item");
PropertyInfo propertyB = typeof(TOut).GetProperty("Item");
int count = (int)typeof(TIn).GetProperty("Count").GetValue(request);
for (int i = 0; i < count; i++)
{
var value = propertyA.GetValue(request, new object[] { i });
var b = CreateBFromA(propertyB, propertyA, value);
propertyB.SetValue(response, b, new object[] { i });
}
return response;
}
private static object CreateBFromA(PropertyInfo propertyB, PropertyInfo propertyA, object value)
{
var b = Activator.CreateInstance(propertyB.PropertyType);
object o = propertyA.PropertyType.GetProperty("Data").GetValue(value);
propertyB.PropertyType.GetProperty("Data").SetValue(b, o);
return b;
}
}
internal class ClassA
{
public string Data { get; set; }
}
internal class ClassB
{
public string Data { get; set; }
public object Other { get; set; }
}
This is a small example code of a bigger generic method (where I need to use reflection), so you can try and run it to regenerate the exception.
How to use the SetValue method to avoid this exception?
Here is my aproach to it:
public static TCollectionOut ConvertCollection<TCollectionIn, TCollectionOut, TIn, TOut>(TCollectionIn input)
where TCollectionIn : IEnumerable<TIn>
where TCollectionOut : ICollection<TOut>, new()
where TOut : new()
{
var res = new TCollectionOut();
foreach (dynamic item in input)
{
dynamic o = new TOut();
ConvertItem(item, o);
res.Add(o);
}
return res;
}
public static TCollectionOut ConvertCollectionMoreDynamic<TCollectionIn, TCollectionOut>(TCollectionIn input)
where TCollectionIn : IEnumerable
{
dynamic res = Activator.CreateInstance(typeof (TCollectionOut));
var oType = typeof (TCollectionOut).GetMethod("Add").GetParameters().Last().ParameterType;
foreach (dynamic item in input)
{
dynamic o = Activator.CreateInstance(oType);
ConvertItem(item, o);
res.Add(o);
}
return res;
}
public static void ConvertItem(ClassA input, ClassB output)
{
output.Data = input.Data;
}
If you wich to support more types just create ConvertItem method with correct overload.
This is because you are trying to pass an index to a not indexed property (Data).
If you post the ClassA code I can try yo help. Anyway you can use LINQ to perform this kind of conversions. It's faster (to write and to execute) and type safe.
I have a delegate expecting parameters of type A as parameters. So A is the base class. Class B and C inherit from A.
The problem is that although B and C inherit from the base class A, the DoSomething functions at the bottom of the script can't be converted to the delegate.
public class A { }
public class B : A { }
public class C : A { }
public delegate void CallbackAction(params A[] paremeters);
public class Main
{
public int main(params string[] args)
{
CallbackAction callbackAction;
callbackAction = DoSomething1;
callbackAction = DoSomething2;
callbackAction = DoSomething3;
return 0;
}
public void DoSomething1(A arg0) { }
public void DoSomething2(B arg0) { }
public void DoSomething3(C arg0) { }
}
Is there any way to use params in a delegate and be able to use classes that have the params class as their base class?
When compiling the error I get is:
Error 5 No overload for 'DoSomething3' matches delegate 'SKConsole.CallbackAction'
I'm using .NET 4 and XNA
EDIT::
Ok let me explain why I am using this I am creating a console. This means a programmer using my console can add a command (console.AddCommand("help", Help) to the console, Help here is a function. When you are ingame and typing help in the console it will execute the function Help().
I now want it to work with console.AddCommand("setSpeed", SetPlayerSpeed) aswell. The SetPlayerSpeed function has 1 parameter, an int. But I want it to work with any function so if a programmer creates the function DoSomeFancyStuff(float a, string b, int c) I want the console to create a command and if you type in the correct string in the console execute these command.
I already tried making lots of delegates for different functions, but this is kinda ugly in my opinion.
What I then tried was the following
public abstract class SKConsoleParameter
{
protected string value;
public SKConsoleParameter(string value)
{
this.value = value;
}
public string GetRawValue()
{
return value;
}
public abstract bool IsValid();
public abstract object GetValue();
}
public class StringParam : SKConsoleParameter
{
public StringParam(string value) : base(value) { }
public override bool IsValid()
{
return true;
}
public override object GetValue()
{
return value;
}
}
public class IntParam : SKConsoleParameter
{
public IntParam(string value) : base(value) { }
public override bool IsValid()
{
int i;
return int.TryParse(value, out i);
}
public override object GetValue()
{
int i;
if (int.TryParse(value, out i))
return i;
else
return 0;
}
}
Was this does is that if a developer creates a function like:
DoSomethingCool(StringParam s, IntParam i)
Then it can receive the values by using (string)s.GetValue() and (int)i.GetValue()
The StringParam and IntParam classes both inherit from SKConsoleParameter, so i though I could now create the follwoing delegate
void CoolDelegate(params SKConsoleParameter[] parameters)
But this doesn't work.. Because of the abstract problem with class A, B and C at the top of this page
Does anyone have any ideas to counter this problem?
You are looking for the error in the wrong place. C# allows contravariance in delegates' input parameters. The problem with your code is that your delegate takes params A[], while your method takes a single A. This is not allowed. Delcare your delegate as accepting a single A:
delegate void Callback1 (B a) ;
void Test11 (A a) {}
void Test12 (B b) {}
Callback1 c11 = Test11 ; // OK
Callback1 c12 = Test12 ; // OK
Note also that this does not work with array parameters:
delegate void Callback2 (B[] a) ;
void Test21 (A[] a) {}
void Test22 (B[] b) {}
Callback2 c21 = Test21 ; // compile error
Callback2 c22 = Test22 ; // OK
based on your updated code -- try this. As long as your method matches the delegate the contravariance should work as expected in .NET 3.5 or better
public abstract class SKConsoleParameter
{
protected string value;
public SKConsoleParameter(string value)
{
this.value = value;
}
public string GetRawValue()
{
return value;
}
public abstract bool IsValid();
public abstract object GetValue();
}
public class StringParam : SKConsoleParameter
{
public StringParam(string value) : base(value) { }
public override bool IsValid()
{
return true;
}
public override object GetValue()
{
return value;
}
}
public class IntParam : SKConsoleParameter
{
public IntParam(string value) : base(value) { }
public override bool IsValid()
{
int i;
return int.TryParse(value, out i);
}
public override object GetValue()
{
int i;
if (int.TryParse(value, out i))
return i;
else
return 0;
}
}
class Program
{
public delegate void CoolDelegate(params SKConsoleParameter[] parameters);
static void Main(string[] args)
{
var s = new StringParam("Glenn");
var i = new IntParam("12");
var coolDel = new CoolDelegate(DoSomethingCool);
coolDel(s, i);
}
public static void DoSomethingCool(params SKConsoleParameter[] parameters)
{
if (parameters == null) throw new ArgumentNullException("parameters");
foreach (var item in parameters)
{
if (item is IntParam)
{
// do something interesting
continue;
}
if (item is StringParam)
{
// do something else interesting
continue;
}
throw new NotImplementedException("unknown param type");
}
}
}
Try this code:
public class A { }
public class B : A { }
public class C : A { }
public static class Helper
{
public static Action<A> DoSomething;
}
class Program
{
static void Main(string[] args)
{
var a = new A();
var b = new B();
var c = new C();
Helper.DoSomething = new Action<A>(DoSomething1);
Helper.DoSomething = (Action<A>)new Action<B>(DoSomething2);
Helper.DoSomething = (Action<A>)new Action<C>(DoSomething3);
}
public static void DoSomething1(A a) { }
public static void DoSomething2(B a) { }
public static void DoSomething3(C a) { }
}
There is the command hierarchy in my current application.
public interface ICommand
{
void Execute();
}
So, some commands are stateful, some are not.
I need to enumerate IEnumerable in the circular way for some command implementation during command execution.
public class GetNumberCommand : ICommand
{
public GetNumberCommand()
{
List<int> numbers = new List<int>
{
1, 2, 3
};
}
public void Execute()
{
// Circular iteration here.
// 1 => 2 => 3 => 1 => 2 => 3 => ...
}
public void Stop()
{
// Log current value. (2 for example)
}
}
Execute is called from time to time, so it is necessary to store the iteration state.
How to implement that circular enumeration?
I have found two solutions:
Using the IEnumerator<T> interface.
It looks like:
if (!_enumerator.MoveNext())
{
_enumerator.Reset();
_enumerator.MoveNext();
}
Using the circular IEnumerable<T> (yield forever the same sequence): “Implementing A Circular Iterator” - HonestIllusion.Com.
Maybe, there are more ways to achieve it.
What would you recommend to use and why?
Instead of dealing with IEnumerator interface,
foreach (var x in GetSomething())
{
if (someCondition) break;
}
public IEnumerable<int> GetSomething()
{
List<int> list = new List<int>() { 1, 2, 3 };
int index=0;
while (true)
yield return list[index++ % list.Count];
}
Here's one I just implemented as an extension.
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace DroopyExtensions
{
public static class CircularEnumaratorExtensionMethod
{
public static IEnumerator<T> GetCircularEnumerator<T>(this IEnumerable<T> t)
{
return new CircularEnumarator<T>(t.GetEnumerator());
}
private class CircularEnumarator<T> : IEnumerator<T>
{
private readonly IEnumerator _wrapedEnumerator;
public CircularEnumarator(IEnumerator wrapedEnumerator)
{
this._wrapedEnumerator = wrapedEnumerator;
}
public object Current => _wrapedEnumerator.Current;
T IEnumerator<T>.Current => (T)Current;
public void Dispose()
{
}
public bool MoveNext()
{
if (!_wrapedEnumerator.MoveNext())
{
_wrapedEnumerator.Reset();
return _wrapedEnumerator.MoveNext();
}
return true;
}
public void Reset()
{
_wrapedEnumerator.Reset();
}
}
}
}
To use it, all you have to do is
using DroopyExtensions;
class Program
{
static void Main(string[] args)
{
var data = new List<string>() {"One", "Two", "Tree"};
var dataEnumerator = data.GetCircularEnumerator();
while(dataEnumerator.MoveNext())
{
Console.WriteLine(dataEnumerator.Current);
}
}
}
You can use this extension method:
public static IEnumerable<T> Cyclic<T>(this IEnumerable<T> #this)
{
while (true)
foreach (var x in #this)
yield return x;
}
In that way:
public class GetNumberCommand : ICommand
{
private readonly IEnumerator<int> _commandState = new[] { 1, 2, 3 }.Cyclic().GetEnumerator();
public void Execute()
{
_commandState.MoveNext();
var state = _commandState.Current;
//
// Do stuff with state
//
}
public void Stop()
{
var state = _commandState.Current;
// Log state value. (2 for example)
}
}
while (!stop)
{
foreach (var i in numbers)
{
// do something
}
}
I think, the most comfortable way wil be to implement custom collection with custom enumerator and encapsulate circular logic in it.
class Collection<T> : IEnumerable<T>
{
bool circle;
List<T> collection = new List<T>();
public IEnumerable<T> IEnumerable<T>.GetEnumerator()
{
if(circle) return new CustomEnumerator<T>(this);
return circle.GetEnumerator();
}
}
class CustomEnumerator : Enumerator<T> {}
something like this...
You can write a circular enumerable without yield returns.
public class CircularEnumerable<T> : IEnumerable<T>
{
public CircularEnumerable (IEnumerable<T> sequence)
{
InfiniteLoop = sequence.Concat (this);
}
private readonly IEnumerable<T> InfiniteLoop;
public IEnumerator<T> GetEnumerator ()
{
return InfiniteLoop.GetEnumerator ();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator ()
{
return InfiniteLoop.GetEnumerator ();
}
}
public class GetNumberCommand : ICommand
{
public GetNumberCommand()
{
List<int> numbers = new List<int>
{
1, 2, 3
};
infiniteLoopOnNumbers = new CircularEnumerable<int>(numbers).GetEnumerator();
}
IEnumerator<int> infiniteLoopOnNumbers;
public void Execute()
{
infiniteLoopOnNumbers.MoveNext();
}
public void Stop()
{
int value = infiniteLoopOnNumbers.Current;
}
}
Lets say I have a generic class:
class Foo {
// protected Type t;
// public void SetT(string strval) {
// ((Foo<t>)this).Set(strval);
// }
}
class Foo<T> : Foo {
private T val;
public void Set(string strval) {
if (this is Foo<float>) {
this.val = float.Parse(strval);
} else if (this is Foo<int>) {
this.val = int.Parse(strval);
}
}
}
Now I create an object and put it in an ArrayList:
ArrayList a = new ArrayList();
a.Append(new Foo<float>);
And then I forget the type of Foo<>. Now, how do I Set? I tried the obvious candidates:
(Foo)a[0].Set("5.0");
(Foo<a[0].GetType()>)a[0].Set("5.0");
but those failed.
Is there a way I can call that Set method without explicitly knowing the type of Foo<>?
If not, can I somehow save type of Foo into Foo.t, and then uncomment and use Foo.SetT?
Ah, generics. Very nice tool if you know how to use them :-)
Regards,
dijxtra
One way is to make your generic Foo class implement an interface:
interface IFoo {
void Set(string strval);
}
class Foo<T> : IFoo {
private T val;
public void Set(string strval) {
...
}
}
Then you can cast to IFoo and call Set():
((IFoo)a[0]).Set("5.0");
There's absolutely no reason to be using generics here. Generics are intended to be used when the type of operations you will be performing are generic. In other words, they are independent of the type(s) on which they are performed. You are doing the opposite: the operation will be different depending on the types.
Given that, you should remove the generic parameter, make Set() and Foo abstract, and derive appropriate classes to handle the different types:
abstract class Foo
{
public abstract void Set(string value);
}
class FooDouble : Foo
{
double val;
public override void Set(string value)
{
this.val = double.Parse(value);
}
}
// Etc.
Then, you should be storing your Foos in a List<T>:
List<Foo> fooList = new List<Foo>();
fooList.Add(new FooDouble());
Later, you can say this:
fooList[0].Set("5.0");
And it will just work! No need to remember!
You want to override the implementation of Set in the derived classes.
class Foo {
public virtual void Set(string val);
}
class Foo<T> : Foo {
public override void Set(string val);
}
In addition to what Jimmy pointed out for your base class, you could use a generic collection instead of an ArrayList and make use of a type converter:
public interface IFoo
{
void Set(string value);
}
public class Foo<T> : IFoo
{
private T val;
public void Set(string value)
{
var typeConverter = TypeDescriptor.GetConverter(typeof(T));
if(typeConverter.CanConvertFrom(typeof(string)))
{
val = (T)typeConverter.ConvertFromString(value);
}
else
{
throw new InvalidOperationException();
}
}
}
The above will work with either your ArrayList:
ArrayList a = new ArrayList();
a.Append(new Foo<float>());
((IFoo)a[0]).Set("123.4");
Or with a typed collection:
List<IFoo> list = new List<IFoo>();
list.Add(new Foo<float>());
list[0].Set("123.4");
As an added bonus, you don't need to have an if statement in your Set method and try to account for all possible types.
If you want to know the type parameter that was used in you generic, use the GetGenericArguments method.
class Foo<T> {
int input_as_int;
float input_as_float;
public void Set(string strval) {
if (this.GetType().GetGenericArguments().First() == typeof(float)) {
this.input_as_float = float.Parse(strval);
} else if (this.GetType().GetGenericArguments().First() == typeof(int)) {
this.input_as_int = int.Parse(strval);
}
// Else .. throw an exception? return default value? return 0? what makes sense to your application
}
or alternately if you could by pass the Interface entirely and pass the input string in the constructor.
public class Foo<T>
{
public Foo (string input)
{
var typeConverter = TypeDescriptor.GetConverter(typeof(T));
if (typeConverter.CanConvertFrom(typeof(string)))
{
Value = (T)typeConverter.ConvertFromString(input);
}
else
{
throw new InvalidOperationException();
}
}
public T Value { get; set;
}
}
then you can just use it like so.
var test = new List<int> Foo ("3");
using System;
using System.Collections;
using System.Collections.Generic;
class Foo {
}
class Foo<T> : Foo {
private T val;
public void Set(string strval) {
var _type = typeof(T);
val = (T)(_type.InvokeMember("Parse", System.Reflection.BindingFlags.InvokeMethod, null, null, new Object[] { strval }));
}
override public string ToString(){
return String.Format("{0}", val);
}
}
class Sample {
static void Main(string[] args){
ArrayList a = new ArrayList();
a.Add(new Foo<float>());
a.Add(new Foo<int>());
dynamic ax = a[0];
ax.Set("5.5");
ax = a[1];
ax.Set("55");
//EDIT
//But I may have to set the float value to Foo <int> If you forgot
// ((Foo<float>)a[0]).Set("5.5");
// ((Foo<int>)a[1]).Set("55");
Console.WriteLine("{0},{1}", a[0], a[1]);
}
}