List.Foreach() complains cannot convert from 'void' to 'object' - c#

When I tried to run the following code, it tells me the 'cannot convert from 'void' to 'object' on the last line, does anyone know what is wrong with the code?
public static void Main(string[] args)
{
string s = "asfdsanfdjsajfois";
Dictionary<char, int> dict = new Dictionary<char, int>();
s.ToCharArray().ToList().ForEach(a => {
dict[a] = (dict.ContainsKey(a)) ? dict[a]+1 : 1;
});
pln(dict.Keys.ToList().ForEach(a => Console.WriteLine(dict[a])));
}

The problem is clear without providing any more information:
dict.Keys.ToList().ForEach(a => Console.WriteLine(dict[a])) is a statement that doesn't return anything void, and you're passing that to the pln function, that functions accepts and an argument of type object. You need to pass it an object for that type in order to make the compiler happy and for the code to make sense.

Take a look into this part: .ForEach(a => Console.WriteLine(dict[a]); through this you are iterating through each keys in the Dictionary and print them to the console. Actually the Console.WriteLine() method's return type is void which means it is not returning anything. But you are trying to pass something to a method called pln But it is not specified in the question that how the method is defined or what's the value you are expected in that method.
Actually you need not to iterate through keys and then collect values, you can directly fetch values like this:
dict.Select(x=>x.Value).ToList()
If you need to pass each values to the plan method then you should modify the pln method signature like the following:
private static void pln(int p)
{
Console.WriteLine(p);
// Do something here
}
And for this the query will be like dict.ToList().ForEach(x => pln(x.Value));
If you want to pass the values as List then the method signature will be :
private static void pln(List<int> p)
{
// Do something here
}
And for this the query will be like pln(dict.Select(a => a.Value).ToList());

Related

Please explain this convert extension method

I'm trying to make sense of the code below, can someone please explain to me (in simple terms) how and what gets converted. In particular this part is confusing me (this IEnumerable> values)
Code:
public static class ConvertExtensions
{
public static IEnumerable<TTarget> ConvertAll<TSource, TTarget>(this IEnumerable<IConvertModel<TSource, TTarget>> values) => values.Select(value => value.Convert);
}
It's basically, for every value in a collection, call the T.Convert function, (where T is the target type) and return another collection of the converted values.
It doesn't DO any conversion, it hands the conversion off to a different function depending on the output type.
It's a shorthand way of doing something like this:
var convertedValues = new List<TTarget>();
foreach(var value in values)
{
var convertedValue = value.Convert();
convertedValues.Add(convertedValue);
}
return convertedValues;

Why unable to pass List<string> from static method to non-static method C#

I have a static method like this:
private static void UpdateExportDate(List<string> lstWithdraw, List<string> lstUnit)
{
ServiceReference3.PSSWebServiceSoapClient pwssc = new ServiceReference3.PSSWebServiceSoapClient("PSSWebServiceSoap12");
((IContextChannel)pwssc.InnerChannel).OperationTimeout = new TimeSpan(2, 0, 0);
pwssc.UpdateInfo(lstWithdraw, lstUnit);
}
In another class, I have a non static method like this:
public void UpdateInfo(List<string> lstWithdraw, List<string> lstUnit)
{
UvAccountConversion uac = new UvAccountConversion();
}
When I run the project, it has an error stated that:
cannot convert from 'System.Collections.Generic.List<string>' to 'string[]'
I have tried to remove the List (which means I only pass 2 strings) and it is successful. However, I want to pass the records as 'List'.
Please help!
The error message itself is "cannot convert from 'System.Collections.Generic.List' to 'string[]'" there is no difference between static and instance methods in terms of parsing parameters.
The error indicates that somewhere you need to have an array instead of a List
A list is not the same as an array, although you can call a method on the list to return an array.
List<string> someList = new List<string>{"a","B","c"};
someList.ToArray(); //string[] containing ["a","B","c"]
Try List.ToArray()
pwssc.UpdateInfo(lstWithdraw.ToArray(), lstUnit.ToArray());

Cannot implicitly convert type System.Collections.Generic.Dictionary<System.Tuple<int,int,string>, AnonymousType#1>

I have the following dictionary in a method:
var nmDict = xelem.Descendants(plantNS + "Month").ToDictionary(
k => new Tuple<int, int, string>(int.Parse(k.Ancestors(plantNS + "Year").First().Attribute("Year").Value), Int32.Parse(k.Attribute("Month1").Value), k.Ancestors(plantNS + "Report").First().Attribute("Location").Value.ToString()),
v => {
var detail = v.Descendants(plantNS + "Details").First();
return
new
{
BaseHours = detail.Attribute("BaseHours").Value,
OvertimeHours = detail.Attribute("OvertimeHours").Value
};
});
I need to return nmDict. The problem is that I cannot figure out how to label my method signature. I have tried the following:
protected IDictionary<XElement, XElement> OvertimereportData(HarvestTargetTimeRangeUTC ranges)
The above gives me this error:
Cannot implicitly convert type System.Collections.Generic.Dictionary<System.Tuple<int,int,string>,AnonymousType#1>' to 'System.Collections.Generic.IDictionary<System.Xml.Linq.XElement,System.Xml.Linq.XElement>'. An explicit conversion exists (are you missing a cast?)
protected IDictionary<Tuple, XElement> OvertimereportData(HarvestTargetTimeRangeUTC ranges)
gives me this error:
'System.Tuple': static types cannot be used as type arguments
I do not know what to do.
The short answer: You can't return anonymous types from a function.
The long answer: Your dictionary's value type is anonymous {BaseHours, OvertimeHours} which cannot be returned from a function or passed as an argument (except as an object, but that does nobody any good unless you go through the hassle of reflecting into it). Either define a class/struct with BaseHours and OvertimeHours in it, or use a tuple. The former is probably slightly better because you can keep the names BaseHours and OvertimeHours; with a tuple you just get Value1 and Value2.
If you are using C# 4.0 than you can return the anonymous via dynamic type. So your method signature would look like this
protected IDictionary<Tuple<int,int,string>, dynamic> OvertimereportData(HarvestTargetTimeRangeUTC ranges)
And through the dynamic object you can find the properties at run time.
Hope this will help you.
When you call the ToDictionary method, the resulting dictionary's type has little to do with the type of elements in your source sequence. It's defined entirely by the data types returned by the key and value expressions you supply to the call. For example, if you were to call:
xelem.Descendants(plantNS + "Month").ToDictionary(
k => int.Parse(k.Attribute("Year").Value),
v => k.Attribute("Year).Value
);
You would get an IDictionary<int, string> because that's what your two expressions returned. To return that from a method, you just need to construct the correct type, based on your expressions.
Your first one is easy:
k => new Tuple<int, int, string>(...)
The second one, though, is going to be a problem. The values in your dictionary are of an anonymous type: you return a new { } without specifying a concrete type name for that value. In general, that is going to make it impossible for you to use that dictionary as a return value or parameter. (It can be done, using some very strange-looking generic techniques, but I wouldn't recommend it.)
The first thing you'll need to do, then, is make a concrete type to hold your values, e.g.
public class HoursContainer
{
public string BaseHours { get; set; }
public string OvertimeHouse { get; set; }
}
and change your Linq query appropriately:
var detail = v.Descendants(plantNS + "Details").First();
return new HoursContainer
{
BaseHours = detail.Attribute("BaseHours").Value,
OvertimeHours = detail.Attribute("OvertimeHours").Value
};
Once you've done this, your dictionary will have a concrete type based on the types of things you specified when you created it:
IDictionary<Tuple<int, int, string>, HoursContainer>
(Note: You could also just use another Tuple<int, int> or whatever here, if you wanted, but the resulting generic type would get unwieldy very fast.)

Get delegate arguments inside delegate

Could someone please help me to understand how to get all parameters passed to delegate inside delegate itself?
I have class :
public class ShopManager : ShopEntities
{
public ShopManager getWhere(Func<Object, Object> dataList)
{
var x = dataList.???; // how to get arguments?
return this;
}
public Object getLike(Object dataValue)
{
return dataValue;
}
}
Then i call it as :
ShopManager shopManager = new ShopManager()
var demo = shopManager.getWhere(xxx => shopManager.getLike("DATA"));
The question is : how to get passed parameters "xxx" and "DATA" inside method getWhere()?
Thanks in advance.
You can't because it's the other way around. You can't get the arguments because the delegate does not hold them; the getWhere method will need to pass a value for the xxx parameter when invoking the delegate. The anonymous method that the delegate refers to will then receive this value as the xxx parameter, and in turn pass the string "DATA" as argument for the dataValue parameter when calling getLike. The argument values as such are not part of the delegate's state.
If you want to get information about the parameters as such (not their values), you can do that:
// get an array of ParameterInfo objects
var parameters = dataList.Method.GetParameters();
Console.WriteLine(parameters[0].Name); // prints "xxx"
If you use:
public ShopManager getWhere(Expression<Func<Object, Object>> dataList)
then you can divide the Expression into its subexpressions and parse them. But I'm not sure if using a delegate like you do is even the right thing.
You can't do it (easily). But I don't understand your idea. For what reason do you need to look into a dataList? This is just an anonymous method, you can call it and get results, you shouldn't need to examine or modify it at all.
What is your idea? Why not just call shopManager.getLike() ?
you can get the name of function by doing something like below.
var x = dataList.GetInvocationList().FirstOrDefault().Method.GetParameters();
sring name = x.FirstOrDefault().Name
this will print name as 'xxx'
Arguments are what you will provide while invoking the delegate via dataList(args), and not by the recipient of the invocation. If you want to provide additional information to getWhere() , you can try the following ....
public ShopManager getWhere(Func<Object, Object> dataList, params object[] additonalData)
{
// inspect the additionalData
}
Thanks for replies guys, i decided to use Expression> instead of common delegate. This allows to get both sides of expression - LHS and RHS.
For those who are interested in answer, this is it :
http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/0f6ca823-dbe6-4eb6-9dd4-6ee895fd07b5?prof=required
Thanks for patience and attention.
public static List<object> GetMethodParameterValues(Delegate method)
{
var target = method.Target;
if (target == null) return null;
var fields = target.GetType().GetFields();
var valueList = fields.Select(field => field.GetValue(target)).ToList();
return valueList;
}

What is the syntax for creating a Dictionary with values as instances of Action<T>?

I need to create a Dictionary object as a member field
key = string
value = an instance of Action<T> where T could be different per entry, e.g. long, int, string (a ValueType or a RefType)
However can't get the compiler to agree with me here.. To create a member field it seems to need a fixed T specification. I've passed my limit of struggle time before awareness that 'It shouldn't be this difficult'
Might be a generics noob mistake. Please enlighten..
The usage would be something like this
m_Map.Add("Key1",
new delegate(long l) {Console.Writeline("Woohoo !{0}", l.ToString();));
You can't, basically. How would the compiler know what type you were interested in for any particular entry?
You can't even explain a relationship of Dictionary<Type, Action<T>> where each dictionary entry has a key which is a type and an action which uses that type. Generics just doesn't support that relationship.
If you will know the kind when you try to use it, you can just make it a Dictionary<string, Delegate> and cast the value when you fetch it. Alternatively, you could use Action<object> and live with the boxing and cast you'll end up with.
Note that to use anonymous methods or lambda expressions with just Delegate, you'll need to cast - or write a handy conversion method:
public static Delegate ConvertAction<T>(Action<T> action)
{
return action;
}
That way you can write:
Delegate dlg = ConvertAction((long x) => Console.WriteLine("Got {0}", x));
or in the dictionary context:
var dict = new Dictionary<string, Delegate>();
dict["Key1"] = ConvertAction((long x) => Console.WriteLine("Got {0}", x));
You'll still need to cast to the right type when you fetch the value out of the dictionary again though...
A different tack...
Instead of exposing a dictionary directly, you could encapsulate the dictionary in your own type, and have a generic Add method:
public void Add<T>(string key, Action<T> action)
So it would still be a Dictionary<string, Delegate> behind the scenes, but your type would make sure that it only contained values which were delegates taking a single argument.
With different T per entry, perhaps standardise at Action<object>, and cast inside the actual actions?
static void Main() {
var m_Map = new Dictionary<string, Action<object>>();
m_Map.Add("Key1", obj => Console.WriteLine("Woohoo !{0}", obj));
m_Map.Add("Key2", obj => SomeMethod((int)obj));
m_Map["Key1"](123);
m_Map["Key2"](123);
}
static void SomeMethod(int i) {
Console.WriteLine("SomeMethod: {0}", i);
}

Categories