passing SqlDataReader to function as parameter for casting - c#

for casting data of SqlDataReader I do these (example for common data types):
string name = reader["name"].ToString(); //for string
int i = 0; i = int.TryParse(reader["i"].ToString(), out i); //for int
int i = reader.GetInt32(reader.GetOrdinal("i")); //or this again for int
bool b = reader.GetBoolean(reader.GetOrdinal("b")); // for boolean
I want to create a class with these functions:
public static class gd{
public static bool Bool(SqlDataReader rd, string name)
{
return rd.GetBoolean(rd.GetOrdinal(name));
}
public static int Int(SqlDataReader rd, string name)
{
int i=0;
i = int.TryParse(reader["i"].ToString(), out i);
return i;
}
}
and then just use:
int i=c.Int(reader,"i");
bool b=c.Bool(reader,"b");
DateTime dt = c.Date(reader,"dt");
I want to know is it a good idea to pass datareader as parameter? anyone has got a better Idea for casting datareader data?

Yes, it's OK to pass DataReader as parameter (as any other reference type). When you are passing reader, only reference to it is passed to another method. And it's OK to use methods to make your code more readable and maintainable.
You can write extension method in order to simplify your code:
public static class Extensions
{
public static bool GetBoolean(this IDataReader reader, string name)
{
return reader.GetBoolean(reader.GetOrdinal(name));
}
public static int GetInt32(this IDataReader reader, string name)
{
return reader.GetInt32(reader.GetOrdinal(name));
}
}
Usage will look like:
int i = reader.GetInt32("i");
bool b = reader.GetBoolean("b");

Your idea seems fine (passing reference to SqlDataReader doesn't lag application) if you wish to handle exceptions internally. You could use methods provided by SqlDataReader class specifically for getting data in desired formats:
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.aspx
Check if those methods are sufficent for you. If not, your static helper class seems okay, but I'd advise you to avoid duplicating functionality that's already implemented inside SqlDataReader, because what's the point of reinventing the wheel?

Related

Is it possible to change the parameters that a predefined method can take in C#?

Im not sure if this is possible. Im using a method that takes the parameter int but i found myself in a situation where i need to be able to use a float value. Does anyone know if there is anyway to change the parameters that a predefined method can take?
Thanks All
Best
Alex
You can overload a method as follows:
public static float myMethod(float sumNumber)
{
// whatever you need for code here
return sumNumber;
}
public static int myMethod(int sumNumber)
{
// whatever you need for code here
return sumNumber;
}
C# has generics for his type of requirement, where you want to apply a logic indifferent of the type of parameter input
for example :
T foo<T>(T param)
{
return param + 1;
}
//and it can be used like this
int i;
foo<int>(i); // return type is int
float f;
foo<float>(f); // return type is float
Member overloading means creating two or more members on the same type that differ only in the number or type of parameters but have the same name. - Microsoft MSDN
// your method
public static double Inc(int i)
{
return i + 1;
}
// your method (overloaded)
public static double Inc(double d)
{
return d + 1;
}
int i = Inc(3);
double d = Inc(2.0); // You can use the same method with different parameter types
The website www.dotnetperls.com has a lot of nice examples. If you want to see another explanation besides MSDN, you may read this.
You can define a generic class for such methods.
public class GenericMethodsClass<T>
{
public static T myMethod(T sumNumber)
{
// whatever you need for code here
return sumNumber;
}
}
Calling:
GenericMethodsClass<int>.myMethod(1);
GenericMethodsClass<double>.myMethod(1.2);

Can't add TryParseNull extension method to int in C#

I'm trying to add an extension method to int called TryParseNull that takes a string as input and returns the converted integer if successful or null if the string is not a valid integer.
I followed the doubleMe example from this post: using extension methods on int
My extension method is declared like this:
public static class IntExtensions {
public static int? TryParseNull(this string s) {
int dummy;
int? value;
if (int.TryParse(s, out dummy)) {
value = dummy;
}
else {
value = null;
}
return value;
}
}
But when I try to use it like this the compiler complains that it doesn't know what TryParseNull is. I tried both of the below.
int? myNum = int?.TryParseNull("1");
int? myNum = int.TryParseNull("1");
Edit: I think the problem is the parameter this string s, but I'm passing in a string so I'm not sure how to rectify that.
Edit 2: From the answers below I can see what the problem is, but is there a way to have the syntax int.TryParseNull("1")?
Extension methods work on instances of their 'this' parameter, not on the types.
Instead of
int? myNum = int?.TryParseNull("1");
Try
int? myNum = "1".TryParseNull();
Edit:
Incidentally, you can also call the method statically with the 'this' parameter as the first argument.
int? myNum = IntExtensions.TryParseNull("1");
Try
int? myNum = "1".TryParseNull();
Your method is extending string, not int?. It does return int?
int is a framework provided type and the extension method you added was not originally part of the int implementation, so you cannot call it using the Type directly, you would need to call it on the instance of int as others have pointed.
Based on your edit, you're trying to add a static method to an existing class. See the below:
Can I "add" static methods to existing class in the .NET API?
Short answer is you can't, extension methods only work for instances.

Is there a workaround to use static methods by a generic class?

I have a rather simple problem, but there seems to be no solution within C#.
I have around 100 Foo classes where each implement a static FromBytes() method. There are also some generic classes which shall use these methods for its own FromBytes(). BUT the generic classes cannot use the static FromBytes() methods, because T.FromBytes(...) is illegal.
Do I miss something or is there no way to implement this functionality?
public class Foo1
{
public static Foo1 FromBytes(byte[] bytes, ref int index)
{
// build Foo1 instance
return new Foo1()
{
Property1 = bytes[index++],
Property2 = bytes[index++],
// [...]
Property10 = bytes[index++]
};
}
public int Property1 { get; set; }
public int Property2 { get; set; }
// [...]
public int Property10 { get; set; }
}
//public class Foo2 { ... }
// [...]
//public class Foo100 { ... }
// Generic class which needs the static method of T to work
public class ListOfFoo<T> : System.Collections.Generic.List<T>
{
public static ListOfFoo<T> FromBytes(byte[] bytes, ref int index)
{
var count = bytes[index++];
var listOfFoo = new ListOfFoo<T>();
for (var i = 0; i < count; i++)
{
listOfFoo.Add(T.FromBytes(bytes, ref index)); // T.FromBytes(...) is illegal
}
return listOfFoo;
}
}
I think it would be unfair to choose an answer as accepted answer, after all answers and comments have contributed in different ways with their different views. It would be nice if someone writes a good overview about the different approaches with their pros and cons. That should be accepted after it helps future developers best.
The best option would be to simply accept the specific FromBytes function as a delegate to your generic FromBytes function. This avoids both the performance cost and lack of compile time verifiability that comes along with using reflection.
public delegate T FromBytesFunc<T>(byte[] bytes, ref int index);
public static List<T> FromBytes<T>(byte[] bytes, ref int index,
FromBytesFunc<T> function)
{
var count = bytes[index++];
var listOfFoo = new List<T>();
for (var i = 0; i < count; i++)
{
listOfFoo.Add(function(bytes, ref index));
}
return listOfFoo;
}
Note that if you make the method, rather than the class it's in, generic, you can get the compiler to infer the generic argument. It could be called like so:
var list = SomeClass.FromBytes(bytes, ref index, Foo1.FromBytes);
The problem is that you're trying to use FromBytes as an extension method when it's not. From what I gather, you're trying to call the appropriate FromBytes for whatever <T> is, as defined in whatever class you've already created for T.
What you need to do is call the method via reflection.
Try looking at some of these threads for help on how to accomplish this.
Use Reflection to call generic method on object instance with signature: SomeObject.SomeGenericInstanceMethod<T>(T argument)
How do I use reflection to call a generic method?
Calling generic method using reflection in .NET
How to call generic method with a given Type object?
Could you just implement the static FromBytes method generically in a utility class? Then do something like this?
listOf.Add(Utility.FromBytes<T>(bytes, ref index));
That utility method might be a bit ugly if each methods FromBytes is a lot different, but it wouldn't be too bad, it's all code that used to live in each class anyway.
Something like this:
public static class Utility
{
public static T FromBytes<T>(byte[] bytes, ref int index)
{
if (typeof(T) is Foo1)
{
return Foo1.GetBytes(bytes, ref index);
}
//etc....
}
}
You could also hide that reflection code here as pointed out by other answers. Unfortunately there doesn't seem to be a very clean way to do this, but hiding the messy stuff in a utility method may be the best option.
You can use reflection to find the method on that type and then build a delegate for it. Something like:
delegate T FromBytesFunc<T>(byte[] bytes, ref int index);
public static ListOfFoo<T> FromBytes(byte[] bytes, ref int index)
{
FromBytesFunc<T> fromBytes =
(FromBytesFunc<T>)Delegate.CreateDelegate(
typeof(FromBytesFunc<T>), typeof(T).GetMethod("FromBytes")
var count = bytes[index++];
var listOf = new ListOfFoo<T>();
for (var i = 0; i < count; i++)
{
listOf.Add(fromBytes(bytes, ref index));
}
return listOf;
}
You can try something like this:
sealed class RetType
{
public object Value
{
get;
private set;
}
public int Index
{
get;
private set;
}
public RetType(object value, int index)
{
Value = value;
Index = index;
}
}
public class ListOfFoo<T> : System.Collections.Generic.List<T>
{
static readonly Dictionary<Type, Func<byte[], int, RetType>> dic = new Dictionary<Type, Func<byte[], int, RetType>>
{
{
typeof(Foo1),
new Func<byte[], int, RetType>((bytes, index) =>
{
var value = Foo1.FromBytes(bytes, ref index);
return new RetType(value, index);
})
}
// add here others Foo
};
public static ListOfFoo<T> FromBytes(byte[] bytes, ref int index)
{
var count = bytes[index++];
var listOf = new ListOfFoo<T>();
for (var i = 0; i < count; i++)
{
var o = dic[typeof(T)](bytes, index);
listOf.Add((T)o.Value);
index = o.Index;
}
return listOf;
}
}
You build a lookup to finde the method you want to call to build the instance.
Not sure if this works for you, but it is an option:
Define an interface IHaveFromBytesMethod<T> which defines a FromBytes(...) instance method.
Make all Foo# types implement this interface. (If you do not want this instance method to be visible immediately, you could implement the interface explicitly.)
All implementations of the instance method simply forward the call to the static method of that type.
Restrict type parameter T in your ListOfFoo<T> class to implement this interface and to provide a parameterless constructor.
When you need the static method, construct a new dummy object of type T using the parameterless constructor and then call the instance method on that dummy instance.
Interface:
public interface IHaveFromBytesMethod<T>
{
T FromBytes(byte[] bytes, ref int index);
}
One of the Foo# classes:
public class Foo1 : IHaveFromBytesMethod<Foo1>
{
public Foo1()
{
// ...
}
public static Foo1 FromBytes(byte[] bytes, ref int index)
{
// ...
}
public Foo1 FromBytes(byte[] bytes, ref int index)
{
// within the instance method simply call the static method
return Foo1.FromBytes(bytes, ref index);
}
}
The modified ListOfFoo<T> class:
// requires T to implement the interface and provide a parameterless ctor!
public class ListOfFoo<T> : System.Collections.Generic.List<T>
where T : IHaveFromBytesMethod<T>, new()
{
public static ListOfFoo<T> FromBytes(byte[] bytes, ref int index)
{
// create dummy instance for accessing static method via instance method
T dummy = new T();
var count = bytes[index++];
var listOfFoo = new ListOfFoo<T>();
for (var i = 0; i < count; i++)
{
// instead of calling the static method,
// call the instance method on the dummy instance
listOfFoo.Add(dummy.FromBytes(bytes, ref index));
}
return listOfFoo;
}
}
I'd like to thank you all guys, you gave me some insights to think about. I've considered each approach and thought about its pros and con and wrote the following code. What do you think about? I think it is a good compromise for usability, readability and performance. It only lacks the compiler check.
public class ListOfFoo<T> : System.Collections.Generic.List<T>
{
private static readonly FromBytesFunc<T> BytesFromFunc =
(FromBytesFunc<T>)System.Delegate.CreateDelegate(
typeof(FromBytesFunc<T>),
typeof(T).GetMethod("FromBytes"));
private delegate T2 FromBytesFunc<out T2>(byte[] bytes, ref int index);
public static ListOfFoo<T> FromBytes(byte[] bytes, ref int index)
{
var count = bytes[index++];
var listOfFoo = new ListOfFoo<T>();
for (var i = 0; i < count; i++)
{
listOfFoo.Add(BytesFromFunc(bytes, ref index));
}
return listOfFoo;
}
}
This shall be the summary for all future viewers.
Since you cannot just call the method, the main problem is to get the delegate. There are two approaches:
via reflection
from the caller
You might think reflection is slow, but performance is not an issue. If the delegate is stored in a static field, it only needs to be done once per class, because generic types don't share static members.
Compile time verifiability is an issue. If you care much about compile time verifiability you should go with passing the delegate from the caller. If you care more about a clean method call you have to sacrifice the compile time verifiability.
PS: Some people have suggested to have a dictionary or a switch/case or if/else where the delegates are stored. This is something you shouldn't do. This has no advantage over storing the delegate in a static field of the generic class (generic types don't share static members).

Ambiguous call functions in the class

How to get around? I do not want to have functions with different names.
public class DataRowSafe
{
public String Get(String Column)
{
return String.Empty;
}
public int Get(String Column)
{
return 0;
}
}
DataRowSafe r=new DataRowSafe();
String res=r.Get("Column1");
int res2=r.Get("Column2");//<--- Ambiguous call
The overloading of methods requires your similar-named methods to have different signatures. The return-value is insignificant! Have a look at this tutorial here.
You can't, there is no way, the only way would be to have a different signature.
You can you referenced parameners like this instead
public class DataRowSafe
{
public void Get(String Column, ref string myParam)
{
myParam = String.Empty;
}
public void Get(String Column,ref int myParam)
{
myParam = 0;
}
}
int i = 0;
string st = "";
new DataRowSafe().Get("name", ref i);
new DataRowSafe().Get("name", ref st);
you should be getting an error like
'DataRowSafe' already defines a member called 'Get' with the same
parameter types
The return type of the function is not significant but in this case the compiler is confused with the two method available for call and not sure which is to be picked up maybe you could use generics to overcome this
a sample like
public static T GetValue<T>(string column)
{
string returnvalue="";
//process the data ...
return (T)Convert.ChangeType(returnvalue, typeof(T), CultureInfo.InvariantCulture);
}
It is not possible, because overloading works only for different signatures. If signatures are the same then c# compiler will return error.

Is it possible for a function to return two values?

Is it possible for a function to return two values?
Array is possible if the two values are both the same type, but how do you return two different type values?
Can a function return 2 separate values? No, a function in C# can only return a single value.
It is possible though to use other concepts to return 2 values. The first that comes to mind is using a wrapping type such as a Tuple<T1,T2>.
Tuple<int,string> GetValues() {
return Tuple.Create(42,"foo");
}
The Tuple<T1,T2> type is only available in 4.0 and higher. If you are using an earlier version of the framework you can either create your own type or use KeyValuePair<TKey,TValue>.
KeyValuePair<int,string> GetValues() {
return new KeyValuePair<int,sting>(42,"foo");
}
Another method is to use an out parameter (I would highly recomend the tuple approach though).
int GetValues(out string param1) {
param1 = "foo";
return 42;
}
In a word, no.
But you can define a struct (or class, for that matter) for this:
struct TwoParameters {
public double Parameter1 { get; private set; }
public double Parameter2 { get; private set; }
public TwoParameters(double param1, double param2) {
Parameter1 = param1;
Parameter2 = param2;
}
}
This of course is way too specific to a single problem. A more flexible approach would be to define a generic struct like Tuple<T1, T2> (as JaredPar suggested):
struct Tuple<T1, T2> {
public T1 Property1 { get; private set; }
public T2 Property2 { get; private set; }
public Tuple(T1 prop1, T2 prop2) {
Property1 = prop1;
Property2 = prop2;
}
}
(Note that something very much like the above is actually a part of .NET in 4.0 and higher, apparently.)
Then you might have some method that looks like this:
public Tuple<double, int> GetPriceAndVolume() {
double price;
int volume;
// calculate price and volume
return new Tuple<double, int>(price, volume);
}
And code like this:
var priceAndVolume = GetPriceAndVolume();
double price = priceAndVolume.Property1;
int volume = priceAndVolume.Property2;
It is not directly possible. You need to return a single parameter that wraps the two parameters, or use out parameters:
object Method(out object secondResult)
{
//...
Or:
KeyValuePair<object,object> Method()
{
// ..
All of the possible solutions miss one major point; why do you want to return two values from a method? The way I see it, there are two possible cases; a) you are returning two values that really should be encapsulated in one object (e.g. height and width of something, so you should return an object that represents that something) or b) this is a code smell and you really need to think about why the method is returning two values (e.g. the method is really doing two things).
with C# 7, you can now return a ValueTuple:
static (bool success, string value) GetValue(string key)
{
if (!_dic.TryGetValue(key, out string v)) return (false, null);
return (true, v); // this is a ValueType literal
}
static void Main(string[] args)
{
var (s, v) = GetValue("foo"); // (s, v) desconstructs the returned tuple
if (s) Console.WriteLine($"foo: {v}");
}
ValueTuple is a value-type, which makes it a great choice for a return value compared with a reference-type Tuple - no object needs to be garbage-collected.
Also, note that you can give a name to the values returned. It is really nice.
For that reason alone I wish it was possible to declare a ValueTuple with only one element. Alas, it is not allowed:
static (string error) Foo()
{
// ... does not work: ValueTuple must contain at least two elements
}
Not directly. Your options are either to return some kind of custom struct or class with multiple properties, use KeyValuePair if you simply want to return two values, or use out parameters.
You have basically (at least) two options, either you make an out parameter in addition to the return value of the function, something like T1 Function(out T2 second) or you make your own class putting these two types together, something like a Pair<T1,T2>. I personally prefer the second way but it's your choice.
In C# you can return more than one value using an out parameter. See example in the TryParse method of Int32 struct. It returns bool and an integer in an out parameter.
no but you can use an out parameter
int whatitis;
string stuff = DoStuff(5, out whatitis);
public string DoStuff(int inParam, out int outParam)
{
outParam = inParam + 10;
return "donestuff";
}
It is not possible to return more than one value from a function, unless you are returning a type that contains multiple values in it (Struct, Dictionary, etc). The only other way would be to use the "out" or "ref" keywords on the incoming parameters.
You could use the out parameter.
int maxAge;
int minAge;
public int GetMaxAgeAndMinAge(out int maxAge, out int minAge)
{
MaxAge = 60;
MinAge = 0;
return 1; //irrelevant for this example since we care about the values we pass in
}
I really tend to stay away from this, I think that it is a code-smell. It works for quick and dirty though. A more testable and better approach would be to pass an object that represents your domain (the need to see two these two values).
you can try this
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
To return 2 values I usually use Pair class from http://blog.o-x-t.com/2007/07/16/generic-pair-net-class/.
If you need to return from method 2 values that describe the range, e.g. From/To or Min/Max, you can use FromToRange class.
public class FromToRange<T>
{
public T From { get; set; }
public T To { get; set; }
public FromToRange()
{
}
public FromToRange(T from, T to)
{
this.From = from;
this.To = to;
}
public override string ToString()
{
string sRet = String.Format("From {0} to {1}", From, To);
return sRet;
}
public override bool Equals(object obj)
{
if (this == obj) return true;
FromToRange<T> pair = obj as FromToRange<T>;
if (pair == null) return false;
return Equals(From, pair.From) && Equals(To, pair.To);
}
public override int GetHashCode()
{
return (From != null ? From.GetHashCode() : 0) + 29 * (To != null ? To.GetHashCode() : 0);
}
}

Categories