multiple generic overloads - c#

I have a simple helper class that I use to build a simple comma separated string.
private string AddcsvString(string s)
{
if(string.IsNullOrWhiteSpace(this.Value))
{
return s;
}
else
{
return this.Value + "," + s;
}
}
I also have a generic method that calls this
public void Add<T>(T s) where T: struct
{
this.Value = AddcsvString(s.ToString());
}
I wanted to add an overload for a generic List
public void Add<T>(IEnumerable<T> values)where T:struct
{
foreach (T t in values)
{
Add(t.ToString());
}
}
But any attempt to call this called the first generic method. So I ended up renaming the second generic method to AddAll. In the end I think this was the right way to go for this case but would like to know if it is possible to have both for future reference.
--edit
Here is the case that doesn't work
CsvString test = new CsvString();
string result;
test.Add(1);
test.Add('2');
test.Add("3");
result = test.ToString(); // result = "1,2,3"
CsvString test2 = new CsvString();
List<long> aList = new List<long>();
string result2;
aList.Add(1);
aList.Add(2);
aList.Add(3);
test2.Add(aList); //line doesn't compile
--edit 2
I found a second solution (though JoshE below gets credit for answering this, thanks btw).
I changed the second method to this
public SWcsvString Add<T,K>(T values)where T: IEnumerable<K> where K: struct
{
foreach (K k in values)
{
Add(k.ToString());
}
return this;
}
and the call to this
test2.Add<IEnumerable<long>,long>(aList);

Try removing your constraints where T : struct, and I think you will get the proper behavior.
IEnumerable<char> <==> String, since a string is just a char[]. Since a string is not really a value-object, overload resolution will almost always favor the first method to avoid the boxing/unboxing operation of converting a string to IEnumerable<char>. (I'm guessing that you've tried calling it with both "foo" and IEnumerable<bar> where bar is a struct).

Related

Choosing appropriate method using pattern matching in C#

Currently am doing a college project in C# which includes conversion of one form of code to another form of code, which involves choosing appropriate method/function from many methods available. The problem here is, to implement this using any pattern matching techniques rather then using many IF ELSE statements.
For now I have achieved this using nested IF ELSE statements which fills the whole program and looks like childish code on completion.
Current Implementation :--
Input:
//stored in list<string>
get(3 int) //type1
get(int:a,b,c) //type2
get(name) //type3
//list passed to ProcessGET method
Using if else :
public string ProcessGET(List<string> inputData)
{
foreach(var item in inputData)
{
if (inputData.item.Split('(')[1].Split(')')[0].Contains(':'))
{
return Type2 result;
}
else if (!inputData.item.Split('(')[1].Split(')')[0].Contains(':') && Convert.ToInt32(inputData.item.Split('(')[1].Split(')')[0].Split(' ')[0])>0)
{
return Type1 result;
}
else
{
return Type3 result;
}
}
}
How I wanted this to be is something like this,
/stored in list<string>
get(3 int) //type1
get(int:a,b,c) //type2
get(name) //type3
//list passed to ProcessGET method
public string ProcessGET(List<string> inputData)
{
foreach(var itm in inputData)
{
// call appropriate method(itm) based on type using some pattern matching techniques
}
}
string Method1(var data)
{
return result for type1;
}
string Method2(var data)
{
return result for type2;
}
string Method3(var data)
{
return result for type3;
}
Normally my program does mostly this kind of work for various types of input keywords like 'get','output','declare' etc etc etc... where Get is transformed to Scanf statements,output to printf statements and so on.
In such case if i use the IF ELSE, my project is full of If else statements.
As i just started to learn C#, I don't know if such thing exists(googled but didn't found what i was looking for), so any help regarding this problem will be very help(use)ful in further development.
Many Thanks in Advance.
Another general approach to this problem is to introduce an interface, say IMatcher. The interface has one method Match that returns either your type or maybe the fully transformed line.
You create multiple classes that implement IMatcher.
Your main loop then becomes:
var matchers = new [] { new MatcherA(), new MatcherB(), ... };
foreach (string line in input)
foreach (matcher in matchers)
{
var match = matcher.Match(line);
if (match != null) return match;
}
No more big if statement. Each matcher has its own small class and you can write unit tests for each. Also, use RegEx to make your matchers simpler.
I'll leave some suggestions here over which you can have a look at. Here's some basic code.
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
namespace TestStuff
{
class Program
{
//Input string should be of the form "<type>:<index>"
static dynamic GiveMeSomethingDynamic(string someInput)
{
/* predefined arrays sothat we can return something */
string[] _storedStrings = { "Word 1", "word 2", "word 3" };
int[] _storedInts = { 1, 2, 3 };
float[] _storedFloats = { 3.14f, 2.71f, 42.123f };
/* Parse the input command (stringly typed functions are bad, I know.) */
string[] splitted = someInput.Split(':');
string wantedType = splitted[0];
int index = int.Parse(splitted[1]);
/* Decide what to return base on that argument */
switch (wantedType)
{
case "int":
return _storedInts[index];
case "string":
return _storedStrings[index];
case "float":
return _storedFloats[index];
//Nothing matched? return null
default:
return null;
}
}
static void Main(string[] args)
{
/* get some return values */
dynamic firstOutput = GiveMeSomethingDynamic("string:0");
dynamic secondOutput = GiveMeSomethingDynamic("int:1");
dynamic thirdOutput = GiveMeSomethingDynamic("float:2");
/* Display the returned objects and their type using reflection */
Console.WriteLine("Displaying returned objects.\n" +
"Object 1: {0}\t(Type: {1})\n" +
"Object 2: {2}\t\t(Type: {3})\n" +
"Object 3: {4}\t\t(Type: {5})\n",
firstOutput, firstOutput.GetType(),
secondOutput, secondOutput.GetType(),
thirdOutput, thirdOutput.GetType());
/* Act on the type of a object. This works for *all* C# objects, not just dynamic ones. */
if (firstOutput is string)
{
//This was a string! Give it to a method which needs a string
var firstOutputString = firstOutput as string; //Cast it. the "as" casting returns null if it couldn't be casted.
Console.WriteLine("Detected string output.");
Console.WriteLine(firstOutputString.Substring(0, 4));
}
//Another test with reflection.
Console.WriteLine();
//The list of objects we want to do something with
string[] values = { "string:abcdef", "int:12", "float:3.14" };
foreach(var value in values)
{
/* Parse the type */
string[] parsed = value.Split(':');
string _type = parsed[0];
string _argument = parsed[1];
switch (_type)
{
case "string":
//This is a string.
string _stringArgument = _argument as string;
Method1(_stringArgument);
break;
case "int":
//Do something with this int
int _intArgument = int.Parse(_argument);
Method2(_intArgument);
break;
case "float":
float _floatArgument = float.Parse(_argument);
Method3(_floatArgument);
break;
default:
Console.WriteLine("Unrecognized value type \"{0}\"!", _type);
break;
}
}
Console.ReadLine();
}
public static void Method1(string s) => Console.WriteLine("String Function called with argument \"{0}\"", s);
public static void Method2(int i) => Console.WriteLine("int Function called with argument {0}", i);
public static void Method3(float f) => Console.WriteLine("float Function called with argument {0}", f);
}
}
The first approach, given by the function GiveMeSomethingDynamic() relies on the dynamic keyword, which can return arbitrary types. Depending on the input string, it can return a string, an int or a float. The method is called in the Main() function and the type of the returned objects is checked with e.g. firstOutput is string (the is operator). It could have also been done withif( firstOutput.GetType() == typeof(string))`.
The second approach would be a classical "parse and cast" technique. We parse an input string of the format <type>:<value>, then call different functions with the converted or parsed arguments. This is maybe what you want.
There's also a "hacky" way giving a function arbitrary types. There, you can just the dynamic keyword on an input argument, as in
public dynamic superDynamic(dynamic inputVar)
{
//Figure out the type of that object
//return something dynamic
}
The "oldschool" approach (not using dynamic) would be to only pass object types into each function, but the parsing is equivalent (if(someArgument.GetType() == typeof(string))...).
Hope this gives you some ideas on how to parse these strings, cast them to different types and call different functions with it.
So the types are stored as strings in a list, right? And you want to call a different function based on the value of the string?
Here's how I would finish your code:
Create an interface:
public interface IMyType
{
string Result();
string Input {get; set;}
}
and three classes which implement it:
public class Type1 : IMyType
{
public string Result()
{
// do something
}
public string Input {get; set;}
}
(repeat for Type2 and Type3)
3.then create a method which returns one of these three types
based on pattern matching your string input
public IMyType GetAppropriateType(string input)
{
if (inputData.item.Split('(')[1].Split(')')[0].Contains(':'))
{
return new Type2 {Input = input};
}
//etc
}
public string ProcessGET(List<string> inputData)
{
foreach(var itm in inputData)
{
IMyType type = GetAppropriateType(itm);
type.Result();
}
}
Probably worth looking at regex for your string matching too

Indexer in Generic Array

Hi
i have created a Generic Array that works fine for Int,String, Float or even my Own type named Customers.
Generic Array has functions Add(), Sort(), ShowAll() thats working fine for Int, String, and even Customer Type
except when i try to showAll() method for CustomerType that shows all the values that i have added through ADD() method.
output is something like
GenericArray.Customer
not the values where as i wanted to have the values .
i have solved it through
public class GArray<T> where T : Customer
but now i cant create Generic Array of type Int,Float .
here is the ADD and ShowAll method of Class
public void Add(T temp)
{
if (index >= values.Length)
{
T[] tempArray = new T[values.Length + 1];
Array.Copy(values, tempArray, values.Length);
values = tempArray;
}
values[index] = temp;
index++;
}
public void ShowAll()
{
for (int i = 0; i < values.Length; i++)
{
Console.WriteLine(values[i]);
}
}
the values m adding
static void Main(string[] args)
{
GArray<Customer> customers = new GArray<Customer>(3);
customers.Add(new Customer(101, "xyz"));
customers.Add(new Customer(59, "abc"));
customers.ShowAll();
}
i have talked with my frnd and he said that i have to create indexer my self . can some one help me how can i create indexer in this case that works fine for customerType or any Type.
I think,If I understand the question (output is something like GenericArray.Customer, not the values where as i wanted to have the values) you should add in Customer definition:
public override string ToString()
{
// return something you want to show to identify your customer
// e.g. return Name;
return ...
}
I explain: when you use Console.WriteLine(values[i]) you tell C# to write to console Customer object... and it writes out then name of the class, as it's the default behaviour.
Defining in Customer class the default string to be converted to makes what you please...
public T this[int index]
{
get {return values[index]; }
}
I think your problem is that you have not overridden ToString in your customer class. Do that -- it will define how the objects should be displayed in the console.
Your actual problem aside for a moment, I would like to mention that there is no place for a ShowAll method in an array implementation. Why should an array be tied to a console application? Wouldn't you want to reuse it for a Windows Forms application oneday without the need to rewrite it?
Next, .NET already has a List<T> which does dynamic allocation as necessary. If you do want to write it again yourself, at least allocate the array in bigger steps (n*2 each time).
To remove the ShowAll method from the array (where it doesn't belong), you should consider taking one of the following approaches:
a) Create an extension method which works for any IEnumerable<T> (a List, Array, Collection, whatever):
public static class EnumExt
{
public static void ShowAll<T>(this IEnumerable<T> list)
{
foreach (T item in list)
Console.WriteLine(item);
}
}
Usage:
int[] array = new int[] { 1,2,3};
array.ShowAll();
b) Or, be even more abstract and create a ForEach extension method where you will pass an arbitrary delegate to perform actual work:
public static class EnumExt
{
public static void ForEach<T>(this IEnumerable<T> list, Action<T> action)
{
foreach (T item in list)
action(item);
}
}
Usage:
int[] array = new int[] { 1,2,3};
// now you are reusing the iterator
// for any action you want to execute
array.ForEach(Console.WriteLine);
// or
array.ForEach(item => Console.WriteLine("My item is: " + item));

Conditional typing in generic method

Consider the following (heavily simplified) code:
public T Function<T>() {
if (typeof(T) == typeof(string)) {
return (T) (object) "hello";
}
...
}
It's kind of absurd to first cast to object, then to T. But the compiler has no way of knowing that the previous test assured T is of type string.
What is the most elegant, idiomatic way of achieving this behavior in C# (which includes getting rid of the stupid typeof(T) == typeof(string), since T is string can't be used)?
Addendum: There is no return type variance in .net, so you can't make a function overload to type string (which, by the way, is just an example, but one reason why association end redefinition in polymorphism, e.g. UML, can't be done in c#). Obviously, the following would be great, but it doesn't work:
public T Function<T>() {
...
}
public string Function<string>() {
return "hello";
}
Concrete Example 1: Because there's been several attacks to the fact that a generic function that tests for specific types isn't generic, I'll try to provide a more complete example. Consider the Type-Square design pattern. Here follows a snippet:
public class Entity {
Dictionary<PropertyType, object> properties;
public T GetTypedProperty<T>(PropertyType p) {
var val = properties[p];
if (typeof(T) == typeof(string) {
(T) (object) p.ToString(this); // magic going here
}
return (T) TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(val);
}
}
Concrete Example 2: Consider the Interpreter design pattern:
public class Expression {
public virtual object Execute() { }
}
public class StringExpression: Expression {
public override string Execute() { } // Error! Type variance not allowed...
}
Now let's use generics in Execute to allow the caller to force a return type:
public class Expression {
public virtual T Execute<T>() {
if(typeof(T) == typeof(string)) { // what happens when I want a string result from a non-string expression?
return (T) (object) do_some_magic_and_return_a_string();
} else if(typeof(T) == typeof(bool)) { // what about bools? any number != 0 should be True. Non-empty lists should be True. Not null should be True
return (T) (object) do_some_magic_and_return_a_bool();
}
}
}
public class StringExpression: Expressiong {
public override T Execute<T>() where T: string {
return (T) string_result;
}
}
If you're making these types of checks in a generic method, I'd rethink your design. The method is obviously not truly generic - if it were, you wouldn't need specific type checking...
Situations like this typically can be handled more cleanly by a redesign. One alternative is often to provide an overload of the appropriate type. Other design alternatives which avoid the type-specific behavior exist, as well, such as Richard Berg's suggestion of passing in a delegate.
using System;
using System.Collections.Generic;
using System.Linq;
namespace SimpleExamples
{
/// <summary>
/// Compiled but not run. Copypasta at your own risk!
/// </summary>
public class Tester
{
public static void Main(string[] args)
{
// Contrived example #1: pushing type-specific functionality up the call stack
var strResult = Example1.Calculate<string>("hello", s => "Could not calculate " + s);
var intResult = Example1.Calculate<int>(1234, i => -1);
// Contrived example #2: overriding default behavior with an alternative that's optimized for a certain type
var list1 = new List<int> { 1, 2, 3 };
var list2 = new int[] { 4, 5, 6 };
Example2<int>.DoSomething(list1, list2);
var list1H = new HashSet<int> { 1, 2, 3 };
Example2<int>.DoSomething<HashSet<int>>(list1H, list2, (l1, l2) => l1.UnionWith(l2));
}
}
public static class Example1
{
public static TParam Calculate<TParam>(TParam param, Func<TParam, TParam> errorMessage)
{
bool success;
var result = CalculateInternal<TParam>(param, out success);
if (success)
return result;
else
return errorMessage(param);
}
private static TParam CalculateInternal<TParam>(TParam param, out bool success)
{
throw new NotImplementedException();
}
}
public static class Example2<T>
{
public static void DoSomething(ICollection<T> list1, IEnumerable<T> list2)
{
Action<ICollection<T>, IEnumerable<T>> genericUnion = (l1, l2) =>
{
foreach (var item in l2)
{
l1.Add(item);
}
l1 = l1.Distinct().ToList();
};
DoSomething<ICollection<T>>(list1, list2, genericUnion);
}
public static void DoSomething<TList>(TList list1, IEnumerable<T> list2, Action<TList, IEnumerable<T>> specializedUnion)
where TList : ICollection<T>
{
/* stuff happens */
specializedUnion(list1, list2);
/* other stuff happens */
}
}
}
/// I confess I don't completely understand what your code was trying to do, here's my best shot
namespace TypeSquarePattern
{
public enum Property
{
A,
B,
C,
}
public class Entity
{
Dictionary<Property, object> properties;
Dictionary<Property, Type> propertyTypes;
public T GetTypedProperty<T>(Property p)
{
var val = properties[p];
var type = propertyTypes[p];
// invoke the cast operator [including user defined casts] between whatever val was stored as, and the appropriate type as
// determined by the domain model [represented here as a simple Dictionary; actual implementation is probably more complex]
val = Convert.ChangeType(val, type);
// now create a strongly-typed object that matches what the caller wanted
return (T)val;
}
}
}
/// Solving this one is a straightforward application of the deferred-execution patterns I demonstrated earlier
namespace InterpreterPattern
{
public class Expression<TResult>
{
protected TResult _value;
private Func<TResult, bool> _tester;
private TResult _fallback;
protected Expression(Func<TResult, bool> tester, TResult fallback)
{
_tester = tester;
_fallback = fallback;
}
public TResult Execute()
{
if (_tester(_value))
return _value;
else
return _fallback;
}
}
public class StringExpression : Expression<string>
{
public StringExpression()
: base(s => string.IsNullOrEmpty(s), "something else")
{ }
}
public class Tuple3Expression<T> : Expression<IList<T>>
{
public Tuple3Expression()
: base(t => t != null && t.Count == 3, new List<T> { default(T), default(T), default(T) })
{ }
}
}
Can you use as here?
T s = "hello" as T;
if(s != null)
return s;
I can't think of an "elegant" way to do this. As you say, the compiler can't know that the conditional has ensured that the type of T is string. As a result, it has to assume that, since there's no generalized way to convert from string to T, it's an error. object to T might succeed, so the compiler allows it.
I'm not sure I'd want an elegant way to express this. Although I can see where it'd be necessary to do explicit type checks like this in some situations, I think I'd want it to be cumbersome because it really is a bit of a hack. And I'd want it to stick out: "Hey! I'm doing something weird here!"
Ok, I took a run at it from several different angles and came up short. I would have to conclude that if your current implementation gets the job done you should take the win and move on. Short of some arcane emissions what you got is what you get.
But the compiler has no way of knowing
that the previous test assured T is of
type string.
Umm.... If I am not mistaken, generics is just code gen. The compiler generates a matching method for each distinct type found in the calling methods. So the compiler does know the type argument for the overload being called. Again; If I am not mistaken.
But overall, i think you are misusing the generic in this case, from what I can see, and as others have stated, there are more appropriate solutions..... which are unnamable unless you post code that completely specifies your requirements.
just my 2 pesos...

An example for using predicate to replace 'if' in c#?

I read that the 'if' keyword is evil, and better to use predicate to replace if. Then I googled, but still dont get it.
Can anyone be kind to provide an example?
No matter what they say, if is not evil. There may be specific cases for which a Predicate is a better choice than an if (or a set of ifs).
For example,
foreach (Foo f in fooList) {
if (f.Equals(fooTarget)) {
return f;
}
}
versus (.NET 2.0)
fooList.Find(delegate (Foo f) { return f.Equals(fooTarget); });
or (later)
fooList.Find(f => f.Equals(fooTarget));
They are just different. A predicate is more complex than a simple if statement. A predicate is basically a pointer to a method (delegate) which is tied to a type that it takes as a param and returns true/false.
Imagine you are using generics, and like the find method on generic lists, how can it know what types are in the list prior to your initialization of it. So the find method just uses the predicate and does not know how the predicate will be implemented.
public T Find(Predicate<T> p)
{
//iterate through the collection and return the first match
IEnumerator<T> enumerator = this.GetEnumerator();
while (enumerator.MoveNext())
{
if (p(enumerator.Current))
{
return enumerator.Current;
}
}
return default(T);
}
In this case, a predicate is used but what (p(enumerator.Current)) actually evaluates about enumerator.Current is determined during implementation of the predicate. The code is not aware of what type T wil end up being here.
Here are some ways to assign the predicate to a method
Predicate<string> findShortNames1 = x => x.Length == 3; // lambda expression
Predicate<string> findShortNames2 = delegate(string x) { return x.Length == 3; }; // anonymous method
Predicate<string> findShortNames3 = MatchOnShortNames; //existing method
// ...
private bool MatchOnShortNames(string s)
{
return s.Length == 3;
}
Then the usage is like
someList.FindAll(findShortNames1);
For example, whenever you have a loop like this:
List<Employee> retiredEmployees = new List<Employee>();
foreach (Employee employee in EmployeeList)
{
if (employee.IsRetired)
retiredEmployees.Add(employee);
}
Using a predicate, you would have to change it to:
retiredEmployees = EmployeeList.FindAll(e => e.IsRetired);
But I believe, in the whole "if statement considered evil" debate, predicate vs if is just mentioned as a special case of using OOP and functional programming vs procedural programming. This paradigm can be easily generalized to any delegate type (not just predicate), or any use of OOP to replace a conditional:
For example, if you go through your code, you may easily find code such as this:
public class Employee
{
private bool _isRetired;
private double _amount;
public double GetPayAmount()
{
if (_isRetired)
return _amount * 0.9;
else
return _amount;
}
}
Pure OOP supporters will tell you that you immediately need to extract a different type of employee and handle each branch as a different subtype, which will remove the "evil if statement":
public interface IEmployee
{
double GetPayAmount();
}
public class Employee : IEmployee
{
private double _amount;
public double GetPayAmount()
{
return _amount;
}
}
public class RetiredEmployee : IEmployee
{
private double _amount;
public double GetPayAmount()
{
return _amount * 0.9;
}
}
Although the code is easier to maintain this way, the amount of code in the second case has clearly doubled. For a simple hierarchy as this, there is little need to do the refactoring at this phase. If you decide that you need many more special cases, then your conditional might become too complex, and you can easily refactor it later.
I don't use them for straight "if ... else" constructs myself, other than withinn searches, as it also removes the need for loop constructs. For example
int index = this.listObjects.FindIndex(x => x.PropertyA == objectItem.PropertyA);
or
List<ClassA> listClass = new List<ClassA>();
//... some more code filling listClass with ClassA types ...
ClassA tempClassA = listClass.FirstOrDefault().Where(x=> x.PropertyA == someValue);
I must admit though that if there's just a straight comparison to perform on one item then I use and "if ... else" construct.
static void Main()
{
string[] names = { "Lukasz", "Darek", "Milosz" };
foreach (var item in names)
{
if (ContainsL(item))
Console.WriteLine(item);
}
string match1 = Array.Find(names, delegate(string name) { return name.Contains("L"); });
//or
string match2 = Array.Find(names, delegate(string name) { return name.Contains("L"); });
//or
string match3 = Array.Find(names, x => x.Contains("L"));
Console.WriteLine(match1 + " " + match2 + " " + match3); // Lukasz Lukasz Lukasz
}
static bool ContainsL(string name) { return name.Contains("L"); }

C# Generics and Casting Issue

I am having trouble casting an object to a generic IList. I have a group of in statements to try to work around this, but there has to be a better way to do this.
This is my current method:
string values;
if (colFilter.Value is IList<int>)
{
values = BuildClause((IList<int>)colFilter.Value, prefix);
}
else if (colFilter.Value is IList<string>)
{
values = BuildClause((IList<string>)colFilter.Value, prefix);
}
else if (colFilter.Value is IList<DateTime>)
{
values = BuildClause((IList<DateTime>)colFilter.Value, prefix);
}
else if (...) //etc.
What I want to do is this:
values = BuildClause((IList<colFilter.ColumnType>)colFilter.Value, prefix);
or
values = BuildClause((IList<typeof(colFilter.ColumnType)>)colFilter.Value, prefix);
or
values = BuildClause((IList<colFilter.ColumnType.GetType()>)colFilter.Value, prefix);
Each of these produces this compiler error:
The type or namespace name 'colFilter' could not be found (are you missing a using directive or an assembly reference?)
In my example, colFilter.ColumnType is int, string, datetime, etc. I am not sure why this does not work.
Any ideas?
EDIT: This is C#2.0
EDIT #2
Here is the BuildClause method (I have overloads for each type):
private static string BuildClause(IList<int> inClause, string strPrefix)
{
return BuildClause(inClause, strPrefix, false);
}
private static string BuildClause(IList<String> inClause, string strPrefix)
{
return BuildClause(inClause, strPrefix, true);
}
private static string BuildClause(IList<DateTime> inClause, string strPrefix)
{
return BuildClause(inClause, strPrefix, true);
}
//.. etc for all types
private static string BuildClause<T>(IList<T> inClause, string strPrefix, bool addSingleQuotes)
{
StringBuilder sb = new StringBuilder();
//Check to make sure inclause has objects
if (inClause.Count > 0)
{
sb.Append(strPrefix);
sb.Append(" IN(");
for (int i = 0; i < inClause.Count; i++)
{
if (addSingleQuotes)
{
sb.AppendFormat("'{0}'", inClause[i].ToString().Replace("'", "''"));
}
else
{
sb.Append(inClause[i].ToString());
}
if (i != inClause.Count - 1)
{
sb.Append(",");
}
}
sb.Append(") ");
}
else
{
throw new Exception("Item count for In() Clause must be greater than 0.");
}
return sb.ToString();
}
There's no way to relate method overloading and generics: although they look similar, they are very different. Specifically, overloading lets you do different things based on the type of arguments used; while generics allows you to do the exact same thing regardless of the type used.
If your BuildClause method is overloaded and every overload is doing something different (not just different by the type used, but really different logic, in this case - choosing whether or not to add quotes) then somewhere, ultimately, you're gonna have to say something like "if type is this do this, if type is that do that" (I call that "switch-on-type").
Another approach is to avoid that "switch-on-type" logic and replace it with polymorphism. Suppose you had a StringColFilter : ColFilter<string> and a IntColFilter : ColFilter<int>, then each of them could override a virtual method from ColFilter<T> and provide its own BuildClause implementation (or just some piece of data that would help BuildClause process it). But then you'd need to explicitly create the correct subtype of ColFilter, which just moves the "switch-on-type" logic to another place in your application. If you're lucky, it'll move that logic to a place in your application where you have the knowledge of which type you're dealing with, and then you could explicitly create different ColFilters at different places in your application and process them generically later on.
Consider something like this:
abstract class ColFilter<T>
{
abstract bool AddSingleQuotes { get; }
List<T> Values { get; }
}
class IntColFilter<T>
{
override bool AddSingleQuotes { get { return false; } }
}
class StringColFilter<T>
{
override bool AddSingleQuotes { get { return true; } }
}
class SomeOtherClass
{
public static string BuildClause<T>(string prefix, ColFilter<T> filter)
{
return BuildClause(prefix, filter.Values, filter.AddSingleQuotes);
}
public static string BuildClause<T>(string prefix, IList<T> values, bool addSingleQuotes)
{
// use your existing implementation, since here we don't care about types anymore --
// all we do is call ToString() on them.
// in fact, we don't need this method to be generic at all!
}
}
Of course this also gets you to the problem of whether ColFilter should know about quotes or not, but that's a design issue and deserves another question :)
I also stand by the other posters in saying that if you're trying to build something that creates SQL statements by joining strings together, you should probably stop doing it and move over to parameterized queries which are easier and, more importantly, safer.
What does the function BuildClause() look like.
It seems to me that you can create BuildClause() as an extension method on IList, and you can append the values together. I assume that you just want to call .ToString() method on different types.
If you use generics properly in C# 3.0, you can achieve what you need through implicit typing (int C# 2.0 you might need to specify the type). If your BuildClause method is made generic, it should automatically take on whatever type is passed in to its generic parameter(s):
public IList<T> BuildClause<T>(IList<T> value, object prefix)
{
Type type = typeof(T);
if (type == typeof(string))
{
// handle string
}
else if (type == typeof(int))
{
// handle int
}
// ...
}
public class ColumnFilter<T>:
where T: struct
{
public IList<T> Value { get; set; }
}
var colFilter = new ColumnFilter<string>
{
Value = new { "string 1", "string 2", "string 3" }
}
IList<string> values = BuildClause(colFilter.Value, prefix);
With generics, you can drop the ColumnType property of your ColumnFilter. Since it is generic, along with your BuildClause method, you are easily able to determine the type by doing typeof(T).
I am having trouble casting an object to a generic
Casting is a run-time operation.
Generic is compile-time information.
Don't cross the streams.
Also - if you used a decent sql parameterization generator - it will add the single quotes for you.
I don't understand the question. It works for me. It could be as simple as droping the cast? What am I missing?
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication1 {
class Foo<T> : List<T> {
}
class Program {
static void Main(string[] args) {
var a = new Foo<int>();
a.Add(1);
var b = new Foo<string>();
b.Add("foo");
Console.WriteLine(BuildClause(a, "foo", true));
Console.WriteLine(BuildClause(b, "foo", true));
}
private static string BuildClause<T>(IList<T> inClause, string strPrefix, bool addSingleQuotes) {
StringBuilder sb = new StringBuilder();
//Check to make sure inclause has objects
if (inClause.Count == 0)
throw new Exception("Item count for In() Clause must be greater than 0.");
sb.Append(strPrefix).Append(" IN(");
foreach (var Clause in inClause) {
if (addSingleQuotes)
sb.AppendFormat("'{0}'", Clause.ToString().Replace("'", "''"));
else
sb.Append(Clause.ToString());
sb.Append(',');
}
sb.Length--;
sb.Append(") ");
return sb.ToString();
}
}
}
The type for the IList must be known at compile time. Depending on what you want to do, you might be able to cast the list to an IList or IEnumerable (without generics) and then iterate over the objects

Categories

Resources