Better approach when obtaining multiple values from the same method at once - c#

I have the following method which returns a tuple,
public Tuple<int, bool> GetStudentInformation(long stutID)
Called as,
Marks= GetStudentInformation((Id).Item1;
HasPassed= GetStudentInformation((Id).Item2;
This works fine as it is but I dont like that I call the same method twice to get item1 and item2, using Tuple is probably not the way ahead but any advice if c# has support to get two values returned over a single execution of the method?

You just need to save return value
Tuple<int, bool> info = GetStudentInformation(Id);
Marks = info.Item1;
HasPassed = info.Item2;

example of a clearer way I prefer when using tuples:
public (int data1, bool data2) GetStudentInformation(Id) {
return (123, true);
}
var studentInfo = GetStudentInformation(111);
Console.Write(studentInfo.data1);
Console.Write(studentInfo.data2);

Related

How to collect a single property in a list of objects?

Is it possible to create an extension method to return a single property or field in a list of objects?
Currently I have a lot of functions like the following.
public static List<int> GetSpeeds(this List<ObjectMotion> motions) {
List<int> speeds = new List<int>();
foreach (ObjectMotion motion in motions) {
speeds.Add(motion.Speed);
}
return speeds;
}
This is "hard coded" and only serves a single property in a single object type. Its tedious and I'm sure there's a way using LINQ / Reflection to create an extension method that can do this in a generic and reusable way. Something like this:
public static List<TProp> GetProperties<T, TProp>(this List<T> objects, Property prop){
List<TProp> props = new List<TProp>();
foreach (ObjectMotion obj in objects) {
props.Add(obj.prop??);
}
return props;
}
Apart from the easiest method using LINQ, I'm also looking for the fastest method. Is it possible to use code generation (and Lambda expression trees) to create such a method at runtime? I'm sure that would be faster than using Reflection.
You could do:
public static List<TProp> GetProperties<T, TProp>(this IEnumerable<T> seq, Func<T, TProp> selector)
{
return seq.Select(selector).ToList();
}
and use it like:
List<int> speeds = motions.GetProperties(m => m.Speed);
it's questionable whether this method is better than just using Select and ToList directly though.
It is, no reflection needed:
List<int> values = motions.Select(m=>m.Speed).ToList();
A for loop would be the fastest I think, followed closely by linq (minimal overhead if you don't do use closures). I can't image any other mechanism would be any better than that.
You could replace the List<int> with a int[] or initialize the list with a certain capacity. That would probably do more to speed up your code than anything else (though still not much).

Get values from an enum into a generic List

I don't know how to convert the following line from VB to C#:
Dim values As New List(Of T)(System.Enum.GetValues(GetType(T)))
My version doesn't work:
List<T> values = new List<T>(System.Enum.GetValues(typeof(T)));
The best overloaded method match for
'System.Collections.Generic.List.List(System.Collections.Generic.IEnumerable)'
has some invalid arguments
The constructor-parameter doesn't take it that way - what cast (or else) am I missing?
For clarification: It is wrapped up within the following generic method
public static void BindToEnum<T>()
{
List<T> values = new List<T>(System.Enum.GetValues(typeof(T)));
//...
}
Using LINQ:
List<T> list = System.Enum.GetValues(typeof(T))
.Cast<T>()
.ToList<T>();
Just add a .Cast<T>():
List<T> values = new List<T>(System.Enum.GetValues(typeof(T)).Cast<T>());
Based on this post, I created myself a function to do this for me; It's great in Unit Tests when you want to loop through all values of an Enum to verify something only works on certain values.
public static IEnumerable<T> GetEnumValues<T>()
{
return Enum.GetValues(typeof(T)).Cast<T>();
}
Then I can use it like so:
var values = GetEnumValues<SomeTypeCode>();
var typesToAlwaysShow = values.Where(ScreenAdapter.AlwaysShowThisType).Select(q => (int)q).ToList();
Assert.Equal("101,102,105,205", string.Join(",", typesToAlwaysShow));

Create an enumeration of one

If I want an empty enumeration, I can call Enumerable.Empty<T>(). But what if I want to convert a scalar type to an enumeration?
Normally I'd write new List<string> {myString} to pass myString to a function that accepts IEnumerable<string>. Is there a more LINQ-y way?
You can use Repeat:
var justOne = Enumerable.Repeat(value, 1);
Or just an array of course:
var singleElementArray = new[] { value };
The array version is mutable of course, whereas Enumerable.Repeat isn't.
Perhaps the shortest form is
var sequence = new[] { value };
There is, but it's less efficient than using a List or Array:
// an enumeration containing only the number 13.
var oneIntEnumeration = Enumerable.Repeat(13, 1);
You can also write your own extension method:
public static class Extensions
{
public static IEnumerable<T> AsEnumerable<T>(this T item)
{
yield return item;
}
}
Now I haven't done that, and now that I know about Enumerable.Repeat, I probably never will (learn something new every day). But I have done this:
public static IEnumerable<T> MakeEnumerable<T>(params T[] items)
{
return items;
}
And this, of course, works if you call it with a single argument. But maybe there's something like this in the framework already, that I haven't discovered yet.

Can parameters be generically accessed?

I have a lot of functions that look like this. Each has N arguments and each creates an SQLparamater array with each paramater being of this very similar form.
[WebMethod]
public static string accessServer(string dataField1, string dataField2, string dataField3) {
string value;
SQLParamater[] param = new SQLParameter[len] // len is the amount of arguments
param[0] = new SQLParameter("#dataField1", dataField1);
param[1] = new SQLParameter("#dataField2", dataField2);
param[2] = new SQLParameter("#dataField3", dataField3);
...
// do something with param
return value;
}
This looks like it can be done generically using a combination of Reflection and accessing the paramaters in a generic way.
Ideally a method of the form
public static SQLParamater[] getParams(someType paramaters)
and SQLParamater[] param = getParams(...)
I'm not sure how to pass on all the paramaters generically.
[Edit]
Note that the names of these datafields are important. It's not just an array of strings but rather a set of key/value pairs.
[/Edit]
You can use a function with variable arguments: name(params string[] arguments), so you can call, for example: name(arg1,arg2,arg3,arg4);
This has been asked about before (can't find that question though), the problem however is that while you can figure out the parameter names by using reflection MethodBase.GetCurrentMethod() you can't zip those names together with the parameter values because there's no way for you to access a parameter list of values.
There are other ways of trying to work around this very specific tiresome problem but I don't recommend doing it this way, it just doesn't make a lot of sense.
Now, given a method like this:
static void SomeMethod(string arg1, int arg2, object arg3)
{
}
You could do this:
static void Main()
{
var b = 123;
// this now becomes necessary as it's the only way of getting at the metadata
// in a presumable safe manner
Expression<Action> x = () => SomeMethod("a", b, "a" + b);
var args = GetArgs(x);
foreach (var item in args)
{
Console.WriteLine("{0}: {1}", item.Key, item.Value);
}
}
And implement the GetArgs method like so (you still need a way of putting those values somewhere becuase the invocation never occurs):
static IDictionary<string, object> GetArgs(Expression<Action> x)
{
var args = new Dictionary<string, object>();
var m = (MethodCallExpression)x.Body;
var parameters = m.Method.GetParameters();
for (int i = 0; i < m.Arguments.Count; i++)
{
// an easy way of getting at the value,
// no matter the complexity of the expression
args[parameters[i].Name] = Expression
.Lambda(m.Arguments[i])
.Compile()
.DynamicInvoke();
}
return args;
}
You infer the collection of name/value pairs from the expression tree created by the compiler, it's doable but kind of odd.
I think your API design is flawed if you need this, you would better have one method, which accepts a collection of some sort.
Code duplication like this is almost never the correct way to get things done.
EDIT
On topic:
I guess you can get the values from the stack: http://www.thescarms.com/dotnet/StackFrame.aspx
we do it like this:
var dict=new Dictionary
{
{"#param1",value1},
{"#param2",value2},
{"#param3",value3},
{"#param4",value4},
....
};
DALayer.ExecuteProc("procName",dict);
In the ExecuteProc function you can iterate over Dictionary object and set params using KeyValuePair object. But if you have to setup the datatype, lengths etc for the parameters then you have to do more work like preparing the sql command to query about parameters or passing more complicated object as parameter that contains information about datatype, length and direction etc.

Simple linq question: using linq to get an array of properties

Lets say we have a simple class
public class Foo
{
public string FooName;
}
Now we want to do some simple work on it.
public void SomeCallerMethod(List<Foo> listOfFoos)
{
string[] fooNames = listOfFoo. // What to do here?
}
If I even knew what method to call, I could probably find the rest of the peices.
You want to transform a list of your class into an array of strings. The ideal method for this is Select, which operates on each element on the enumerable and builds a new enumerable based on the type you return.
You need to put a lambda expression into the select method that returns the name, which will simply be "for each element, select the name".
You then need to cast the output as an array.
string[] fooNames = listOfFoos.Select(foo => foo.FooName).ToArray();
Or, using the other syntax:
string[] fooNames = (from foo in listOfFoos
select foo.FooName).ToArray();

Categories