I have a datarow filled with ints stored as strings.
I can parse each one like so: Convert.ToInt32(row[1].ToString())
It works, but is a bit unsightly. I got the idea that maybe I could use an extension class to try and make a .ToInt method. Simplifies things a bit. After some research, I wrote this up:
static class DataRowHelper
{
public static int ToInt(this DataRow row)
{
return Convert.ToInt32( row.ToString());
}
}
This almost gets me there, but the problem is that it attaches the new method to the row like this: row.ToInt() instead of of attaching it like this: row[1].ToInt()
What am I missing here?
I feel the other answers are offering solutions, but not answers.
The reason your extension method isn't working is because the return type of the indexer of your DataRow - row[1] isn't a DataRow, it's a string.
You should enhance your extension method to allow for this indexer:
public static class DataRowExtensions
{
public static int ToInt(this DataRow row, int index)
{
return Convert.ToInt32(row[index].ToString());
}
}
You don't have to apply your own extension method to achieve what you're describing in your question, because the MS team already wrote one for you (terrybozzio hinted at it in a comment).
Instead of using syntax like this:
var id = Convert.ToInt32(row[1]);
var id = Convert.ToInt32(row["id"]);
There's a strongly-typed Field extension method that allows you to specify the data type:
var id = row.Field<int>(1);
var id = row.Field<int>("id");
I can't imagine you'll get much shorter or clearer than that by writing your own extension method.
You could just add the column number as a parameter:
int i1 = row.ToInt(1);
int i2 = row.ToInt(2);
etc.
in which case the extension method would be (error handling not included):
public static int ToInt(this DataRow row, int column)
{
return Convert.ToInt32(row[column].ToString());
}
Even better if you want to handle generics and DbNull:
static class DataRowHelper
{
public static int ToInt(this object item)
{
return Convert.ToInt32(item == null ? 0 : item);
}
}
This is not very exception-safe, and will throw on quite a few conditions. You might want to add some checking here, or implement a TryToInt() type method.
Your extension method should inherit a string, not a DataRow. It should look like this (keep in mind this is very simple... and you should probably include error handling of some sort):
static class DataRowHelper
{
public static int ToInt(this string item)
{
return Convert.ToInt32(item);
}
}
Related
Right so i have a class I'm using to store a set of values
public class dataSet
{
public int Number;
public double Decimal;
public string Text;
//etc...
}
Then I've made an array of type dataSet
public static dataSet[] dataOne = new dataSet[100];
And i'm trying to sort the array of dataOne relevant to the values stored in the int Number stored within dataSet.
I have a sort algorithm ready but i'm struggling to pass in the values stored solely in dataOne.Number so it just ends up being an integer array that i'm passing to the sort.
I'm a total noob at programming so any help would be greatly appreciated.
Edit:
I need to call my sort function by passing it in the array of dataOne.Number if this is possible? So it's basically just passing the sort function an int[]
Give you already have data into your array named dataOne, you could try:
Linq Solution
Use linq to sort it, try this:
dataOne = dataOne.OrderBy(x => x.Number).ToArray();
Remember to add the namespace System.Linq to have access into these methods.
OrderBy allows you to pass an expression to sort data and it will return an IOrderedEnumerable. The ToArray will convert it to an array.
Not Linq Solution
If you are not allowed to use Linq. You could implement an class that implements IComparer<T> and implement the method Compare which takes two generics arguments. Use an instance of this comparer type to sort your data.
For sample, since you have your dataSet type defined, you could implement the comparer:
public class DataSetComparer : IComparer<dataSet>
{
public int Compare(dataSet x, dataSet y)
{
// define the logic to sort here...
return x.Number.CompareTo(y.Number);
}
}
And then, use the comparer on the Array.Sort method:
Array.Sort(dataSet, new NumberComparer());
It will order your dataSets.
I'm not sure I follow why you can't use Linq. But that forces you do to something like this:
var numberValues = new List<int>();
foreach(var dataItem in dataOne)
{
numberValues.Add(dataItem.Number);
}
Then you could pass numberValues.ToArray() to your sort method.
With Linq it would just be
dataOne.Select(d => d.Number).ToArray()
You should have dataset implement IComparable that way you can easily just do...
dataOne = dataOne.OrderBy(x => x).ToArray();
OR...
Array.Sort(dataOne);
Here is how to implement IComparable...
public class dataSet : IComparable
{
public int Number;
public double Decimal;
public string Text;
public int CompareTo(object obj)
{
if (obj == null)
return 1;
dataSet other = obj as dataSet;
if (other != null)
return this.Number.CompareTo(other.Number);
else
throw new ArgumentException("Object is not a dataSet");
}
}
Right now my code looks like this:
var ids = projectId.HasValue ? new List<Guid> { projectId.Value } : new List<Guid>();
Is there a more succinct way of creating a list in one line of code, with one element added optionally?
Another idea for an extension method (the name could definitely be improved, maybe PossiblyCreateSingletonList?):
public static class NullableExtensions
{
public static List<T> SingletonList<T>(this Nullable<T> item) where T : struct
{
return item.HasValue ? new List<T> { item.Value } : new List<T>();
}
}
Usage:
Guid? projectId = null;
List<Guid> projectIds = projectId.SingletonList(); // empty list
I would solve this using a extension method like this:
public static void AddIfNotNull<T>(this List<T> list, T? value) where T : struct
{
if(value != null)
{
list.Add(value.Value);
}
}
Than it could be used like this:
var ids = new List<Guid>();
ids.AddIfNotNull(projectId);
Maybe not as "crafty" (and not a one-liner) as your proposal, but in my opinion it is much easier to read and understand. If desired to be used as a one-liner you could modify the return type of the extension to be the list. That would make it possible to be used something like var ids = new List<Guid>().AddIfNotNull(projectId);
This probably isn't a good idea, but in C# 6, collection initializers also work when Add() is an extension method.
This means you can write the extension Add() like this:
public static void Add<T>(this List<T> list, T? item) where T : struct
{
if (item.HasValue)
{
list.Add(item.Value);
}
}
And then this code will do what you want:
var list = new List<Guid> { projectId };
Note that this will only work for value types (because of the T/T? distinction) and there is no simple way to make it work for reference types.
Also, I would find the line above very surprising, being more succinct is not always better. Which is why I actually wouldn't use this code.
That's pretty succinct, but another option would be to use LINQ:
var ids = new[] { projectId }.Where(x => x.HasValue).Select(x => x.Value).ToList();
If you're going the extension method route, it would have to look something like:
public static void AddIfNotNull<T>(this List<T> list, T? value)
where T : struct
{
if (value.HasValue)
{
list.Add(value.Value);
}
}
You'd have to build a second extension method for reference types (where T : class) if you needed.
Imagine in a class you got this Method:
float Do(int a_,string b_){}
I'm trying to do something like this:
float Do(int a_, string b_)
{
var params = GetParamsListOfCurrentMethod(); //params is an array that contains (a_ and b_)
}
Can someone help ?
Why should I want to do thet ?
Imagine you got an Interface:
public Interface ITrucMuch
{
float Do(int a_,string b_);
// And much more fct
}
And a lot of classes implementing that interface
And a special class that also implement interface:
public class MasterTrucMuch : ITrucMuch
{
public floatDo(int a_, string b_)
{
ITrucMuch tm = Factory.GetOptimizedTrucMuch(); // This'll return an optimized trucMuch based on some state
if(tm != null)
{
return tm.Do(a_,b_);
}
else
{
logSomeInfo(...);
}
//do the fallback method
}
As the interface constains a lot of method and as the first lien of all method are always the same (checking if there is a better interface that the current instance and if so call the same method on the instance) I try to make a method of it.
Thx
You could do something like this:
var parameters = MethodBase.GetCurrentMethod().GetParameters();
foreach (ParameterInfo parameter in parameters)
{
//..
}
Have a look at the ParameterInfo class.
var params = GetParamsListOfCurrentMethod();
params is a C# keyword so it can't be used as a variable name as above.
Here's a link on how to use the params keyword
http://msdn.microsoft.com/en-us/library/w5zay9db.aspx
And some example code pulled form the article.
public static void UseParams(params int[] list)
{
for (int i = 0; i < list.Length; i++)
{
Console.Write(list[i] + " ");
}
Console.WriteLine();
}
Use Reflection .NET to get the parameter names for the method.
Using reflection to get method name and parameters
or
http://msdn.microsoft.com/en-us/library/system.reflection.parameterinfo.aspx
you can write your function with dynamic parameter like this:
protected void Do(params object[] list)
{
if (list.Length < 2)
return;
int a_=(int)list[0];
string b_=list[1].ToString();
}
I don't get it. If you want the param values, and this is the method you need to work with, what about simple doing
protected void Do(int a_, string b_)
{
var paramValues = new object[]{a_, b_};
}
Do you want a more generic answer? Then you are duplicating questions Can I get parameter names/values procedurally from the currently executing function? and How to get parameter value from StackTrace
And you can't, basically.
how can I return more than one type in c# function like I want to return string and datatable ?
The simplest answer is to use the DataTable's TableName property.
The more general answer is to use a Tuple<DataTable, string> or write a class or struct.
use ref or out parameters
ref parameter : requires initilization by the caller method.
public string ReturnName(ref int position)
{
position = 1;
return "Temp"
}
public string GetName()
{
int i =0;
string name = ReturnName(ref i);
// you will get name as Temp and i =1
}
// best use out parameter is the TryGetXXX patternn in various places like (int.TryParse,DateTime.TryParse)
int i ;
bool isValid = int.TryParse("123s",out i);
You can define your own class to use as the return type:
class MyReturnType
{
public string String { get; set; }
public DataTable Table { get; set; }
}
and return an instance of that. You could use a Tuple but it's often better to have meaningful type and property names, especially if someone else is going to be working on the software.
Or you could use an out parameter on the function.
The way you go depends on what is suitable for your situation. If the string and the DataTable are two parts of the same thing a class makes sense. If the string is for an error message when creating the DataTable fails an out parameter might be more appropriate.
Use an out parameter:
public string Function(out DataTable result)
Call it like this:
DataTable table;
string result = Function(out table);
use a tuple as a return.
Hy,
i know it sounds a very stupid question.
Here's what i found:
public static List<SomeDTO> GetData(Guid userId, int languageId)
{
// Do something here
}
public static List<int> GetData(Guid userId ,int iNumberOfItems)
{
var result = GetData(userID,0);
return (from r in result select c.id).Take(iNumberOfItems).ToList<int>();
}
I get a compilation error:
ClassLibrary' already defines a member called 'GetData' with the same parameter types
The second only returning the ids of the first function.
I know this isn't working.
I know there's both returning a List<> type ,but they returning differentypes.
Could somebody explain me why?
How can i solve this?
Update This problem is solved on F# !
You can't override based on the return-type. If you look at your method signature, it looks like the following:
public static List<SomeDTO> GetData(Guid, int)
and
public static List<int> GetData(Guid, int)
What you need to do is one of the following:
Change the method names to something clearer.
Make sure that the parameters can identify which method to call
Now, when you call your function, the return type isn't specified. And since the parameters look the same, the compiler doesn't know which function to call. But it doesn't need to make a guess, since the signatures are too similar it complains on compilation.
The return type of a method is not part of the signature.
Which would be called if you coded
object obj = GetData(Guid userId, int languageId); ?
In C#, it's not allowed to have method overloads that differ only by their return types (with the exception of conversion operators though).
Just create two different methods, that's the only way to get around this.
Method overloading only looks at the name of the method and the number and type of it's parameters, not at the type of the return value. That's why you get the error.
If both functions do more or less the same thing, you might solve this by making a generic function, something like:
public static List<T> GetData<T>(Guid userId, int param2)
But that does not seem to be the case in your example.
The other answers here are all valid. The answer you accepted from PatrikAkerstrand has a very good explanation on why you get the compilation error.
In this case I would recommend to change the method name of the second, as it really has a logical difference in what it does. You just don't get the "data", you specifically gets the ID's of the total dataset:
public static List<SomeDTO> GetData(Guid userId, int languageId)
{
// Do something here
}
public static List<int> GetDataIds(Guid userId, int iNumberOfItems)
{
var result = GetData(userID, 0);
return (from r in result select c.id).Take(iNumberOfItems).ToList<int>();
}
Usage:
List<int> ids = GetDataIds(userID, 10);
You could also use same method name, but add a parameter:
public static List<int> GetData(Guid userId, int languageId, int iNumberOfItems)
{
var result = GetData(userID, languageId);
return (from r in result select c.id).Take(iNumberOfItems).ToList<int>();
}
Usage:
List<int> ids = GetData(userID, 0, 10);
Extension methods
Additionally, you could also extend List<SomeDTO> so you can call it directly if you already have a populated list of type List<SomeDTO>:
public static List<int> GetDataIds(this List<SomeDTO> data, Guid userId, int iNumberOfItems)
{
return (from r in data select c.id).Take(iNumberOfItems).ToList<int>();
}
Then you can use it like this:
List<SomeDTO> result = GetData(userID, 0);
// do other stuff here using other aspects of the result...
List<int> ids = result.GetDataIds(userID, 10);
As PaulB said, this is because the return type is not a part of the signature when it comes to overloading. It sees both functions as:
public static List<SomeDTO> GetData(Guid userId, int languageId) -> GetData(Guid, int)
public static List<int> GetData(Guid userId, int iNumberOfItems) -> GetData(Guid, int)