Is there a generic way to make this conversion? - c#

Below code works when I input it with a string like "15" but when I give it an integer like 15, it gives me error saying " Unable to cast object of type 'System.Int32' to type 'System.String".
How can I edit this code to allow for integer inputs also? Note: I make conversion inside for loop
using System;
using System.Threading;
namespace ConsoleApplication24
{
internal class Program
{
public static void ThreadMethod(object o)
{
for (int i = 0; i < Int32.Parse((string)o); i++)
{
Console.WriteLine("ThreadProc: {0}", i);
Thread.Sleep(0);
}
}
private static void Main(string[] args)
{
Thread t = new Thread(new ParameterizedThreadStart(ThreadMethod));
t.Start("15");
t.Join();
}
}
}

Try
public static void ThreadMethod(object o)
{
var limit = o is string ? Int32.Parse((string)o) : (int)o;
// OR var limit = Int32.Parse(o.ToString());
for (int i = 0; i < limit; i++)
{
Console.WriteLine("ThreadProc: {0}", i);
Thread.Sleep(0);
}
}

Just pass an int instead of a string and drop the Int32.Parse((string)o) part and cast o to int.
for (int i = 0; i < (int)o; i++)
If you want to support strings as well, you'll have to do some investigation (here using C# 7's pattern matching):
int val = /* some default */;
if (o is int oInt) val = oInt;
if (o is string oString) val = Int32.Parse(oString);
If you need more data than a single parameter, you'll have to pass an object (and cast that).
class Data
{
string oString { get; set; }
int oInt { get; set; }
}

There are a few things you can do here. By far the easiest is to not use that type of conversion. As you're going to a string, it is very easy:
for (int i = 0; i < Int32.Parse(o.ToString()); i++)...
However, a cleaner way to to that would be to overload your method:
public static void ThreadMethod(object o)
{
ThreadMethod(Int32.Parse(o.ToString()));
}
public static void ThreadMethod(int o)
{
for (int i = 0; i < o; i++)
{
Console.WriteLine("ThreadProc: {0}", i);
Thread.Sleep(0);
}
}
Even though that adds to the amount of code, it makes your methods far more readable. You can also separate out your call to the int method by doing checks before calling it. Oftentimes, you'll run into situations where you'll want to do more than just call the other method. Even still, this way removes the ambiguity and possibility of failure within the method that is doing what you want.

Related

How to overload muti-Generic class in C#?

How to define generic class for mapping muti-class?
I asked the question before,but i want like this
public class BaseRepositoryService<T1,T2,T3...Tn> where T:class
{
maplestory2Context mc = new maplestory2Context();
public T AddEntity(params object [] args)
{
for (int i = 0; i < args.Length; i++)
{
object obj = args[i];
}
}
}
but i am not sure the how many params I would use. thanks.
note:i changed my code below,but it is not convenience.
public class BaseRepositoryService<T> where T:class
{
maplestory2Context mc = new maplestory2Context();
public T AddEntity(T entity,int size)
{
if (size == 2)
{
}
return null;
}
}
public class BaseRepositoryService<T,T2>
where T : class
where T2:class
{
maplestory2Context mc = new maplestory2Context();
public T AddEntity(T entity, int size)
{
if (size == 2)
{
}
return null;
}
}
Answer to this question is you can't.
You need to define n no of classes for that even Microsoft has defined Func delegates 15 or 16 times. You can refer to msdn documentation for confirmation.
If you don't want write those classes manually you may opt for t4 templates as code generator.

Ref in async Task

How I can to pass a reference as a parameter to Async method in Windows Store App ? I'm looking for something like this:
var a = DoThis(ref obj.value);
public async Task DoThis(ref int value)
{
value = 10;
}
But error:
Async methods cannot have ref or out parameters
Has any another way?
Note:I need to pass exactly obj.value. This method would be used by different types of objects, by same type of objects, by one object, but I will pass obj.val_1, obj.val_2 or obj.val_10. All values will be same type (for ex string)
If you don't care about a little overhead and possibly prolonged lifetime of your objects, you could emulate the ref behavior by passing a setter and a getter method to the function, like this:
public async Task DoStuff(Func<int> getter, Action<int> setter)
{
var value1 = getter();
await DoSomeOtherAsyncStuff();
setter(value1 * value1);
}
And call it like this:
await DoStuff(() => obj.Value, x => obj.Value = x);
You could directly pass the object itself and set the value of the corresponding property inside the method:
var a = DoThis(obj);
public async Task DoThis(SomeObject o)
{
o.value = 10;
}
And if you do not have such object simply write one and have the async method take that object as parameter:
public class SomeObject
{
public int Value { get; set; }
}
You can always use the Task<> class and return the desired value. Then Your code would look something like:
var a = DoThis(obj.value);
obj.value = a.Result;
public async Task<int> DoThis(int value)
{
int result = value + 10; //compute the resulting value
return result;
}
EDIT
Ok, the other way to go with this that I can think of is encapsulating the update of the given object's member in a method and then passing an action invoking this method as the task's argument, like so:
var a = DoThis(() => ChangeValue(ref obj.value));
public void ChangeValue(ref int val)
{
val = 10;
}
public async Task DoThis(Action act)
{
var t = new Task(act);
t.Start();
await t;
}
As far as I tested it the change was made in the child thread, but still it's effect was visible in the parent thread. Hope this helps You.
You can't do this as you have it (as you know). So, a few work arounds:
You can do this by passing the initial object since it will be a reference type
var a = DoThis(obj);
public async Task DoThis(object obj) //replace the object with the actual object type
{
obj.value = 10;
}
EDIT
Based upon your comments, create an interface and have your classes implement it (providing it's always the same type you want to pass). Then you can pass the interface which is shared (maybe over kill, depends on your needs, or even unrealistic amount of work).
Or, provide a base class with the property! (I don't like this suggestion but since you're asking for something which can't be done it may suffice although I don't recommend it).
An example of the interface is here (not using what you have, but close enough using a Colsone App)
using System;
namespace InterfacesReferenceTypes
{
class Program
{
static void Main(string[] args)
{
MyClass mc = new MyClass();
DoThis(mc);
Console.WriteLine(mc.Number);
Console.ReadKey();
}
static void DoThis(IDemo id)
{
id.Number = 10;
}
}
class MyClass : IDemo
{
//other props and methods etc
public int Number { get; set; }
}
interface IDemo
{
int Number { get; set; }
}
}
EDIT2
After next comments, you will have to still use an interface, but re assign the value afterwards. I'm sure there is a better way to do this, but this works:
using System.Text;
namespace InterfacesRerefenceTypes
{
class Program
{
static void Main(string[] args)
{
MyClass mc = new MyClass();
Console.WriteLine(mc.Number);
mc.val1 = 3;
mc.val2 = 5;
mc.Number = mc.val2;
DoThis(mc);
mc.val2 = mc.Number;
Console.WriteLine(mc.val2);
Console.ReadKey();
}
static void DoThis(IDemo id)
{
id.Number = 15;
}
}
class MyClass : IDemo
{
public int val1 { get; set; }
public int val2 { get; set; }
public int Number { get; set; }
}
interface IDemo
{
int Number { get; set; }
}
}

TPL with multiple Method calls Console.Write issue

If i use TPL i run into problems in Parse.. Methods i do use Console.Write to build some Line but somtimes one is to fast and writes in the other Methods row. How do i lock or is there some better way?
Parallel.Invoke(
() => insertedOne = Lib.ParseOne(list),
() => insertedTwo = Lib.ParseTwo(list),
() => insertedThree = Lib.ParseThree(list));
Example for Parse.. Methods.
public static int ParseOne(string[] _list) {
Console.Write("blabla");
Console.Write("blabla");
return 0;
}
public static int ParseTwo(string[] _list) {
Console.Write("hahahah");
Console.Write("hahahah");
return 0;
}
public static int ParseThree(string[] _list) {
Console.Write("egegege");
Console.Write("egegege");
return 0;
}
To be able to print your blablas, hahahahs and egegeges as a single entity(indivisible)
you can write your method as:
public static int ParseThree(string[] _list)
{
lock (Console.Out)
{
Console.Write("egegege");
Console.Write("egegege");
}
return 0;
}
Why don't you run all the tasks in one thread, one after the other?
System.Threading.Tasks.Task.Factory.StartNew(()=>
{
insertedOne = Lib.ParseOne(list);
insertedTwo = Lib.ParseTwo(list);
insertedThree = Lib.ParseThree(list);
});
This way you won't have that much of a race condition.

Declaring an array of base class and instantiating inherited members

I have a class defined with a generic:
public class GenericDataStore<T>
{
// UnderlyingDataStore is another class that manages a queue, or a linked list
private UnderlyingDataStore<T> dataQueue = new UnderlyingDataStore<T>();
public void addData(T data) { dataQueue.Add(data); }
public T getLastData() { dataQueue.getLastData(); }
}
I then have different derived classes based on this class:
public class ByteDataStore : GenericDataStore<Byte>
{
}
public class DoubleDataStore : GenericDataStore<Double>
{
}
public class PObjDataStore : GenericDataStore<PObj> // PObj is another class declared somewhere
{
}
Then, I have a "Manager" class that looks like:
public class DataManager
{
/* Here, I want to declare a 2 dim array [,] that holds pointers to the
data stores. Depending on some other variables, the array may need
to point to DoubleDataStore, ByteDataStore, etc. The following doesn't work,
since GenericDataStore must be declared with a generic type: */
GenericDataStore [,] ManagedDataStores; // Can not compile
public DataManager() {
for (int i=0; i<numStores; i++) {
for (int j=0; j<numCopies; j++) {
// objType is a utility function that we have that returns a type
if (objType(i,j) == typeof(Byte)) {
ManagedDataStores[i,j] = new ByteDataStore();
} else if (objType(i,j) == typeof(double)) {
ManagedDataStores[i,j] = new DoubleDataStore();
}
}
}
}
void Add(int id, int copyid, Byte data) {
ManagedDataStores[i,j].Add(data);
}
}
There might be other, better ways to do this. Essentially, we want to have different data stores for different object types, which can be managed by a class. We want only this 'manager' class to be exposed to the user (like an API), and no direct access to the underlying classes.
Thanks in advance.
I'm afraid that this is one of those instances where Generic's don't help you one bit. By definition, you must know the generic type at compile time, rather than runtime. For runtime type-indiference, you need to do it the old-fashioned way.
public class DataStore
{
// UnderlyingDataStore is another class that manages a queue, or a linked list
private UnderlyingDataStore dataQueue = new UnderlyingDataStore();
public void addData(object data) { dataQueue.Add(data); }
public object getLastData() { dataQueue.getLastData(); }
}
This, has the obvious drawback of boxing/unboxing- as well as the need for calling-code to know what type's it should be dealing with in order to cast.
However, you could also use the other answer, as long as you're able to cast the managedDataStore to the correct generic type.
If you want to create and initialize the double dimensional array use this:
int numStores = 2;
int numCopies = 3;
//GenericDataStore<object>[,] managedDataStores = new GenericDataStore<object>[numStores,numCopies];
Object[,] managedDataStores = new Object[numStores,numCopies];
for (int i = 0; i < numStores; i++)
{
for (int j = 0; j < numCopies; j++)
{
managedDataStores[i,j] = new GenericDataStore<object>();
}
}
I would add an interface and implement it explicitly to hide it from the class users:
internal interface GeneralDataStore
{
void addData(object data);
object getLastData();
}
public class GenericDataStore<T> : GeneralDataStore
{
// UnderlyingDataStore is another class that manages a queue, or a linked list
private UnderlyingDataStore<T> dataQueue = new UnderlyingDataStore<T>();
public void addData(T data) { dataQueue.Add(data); }
public T getLastData() { dataQueue.getLastData(); }
object GeneralDataStore.getLastData() { return getLastData(); }
void GeneralDataStore.addData(object data) { add((T)data); }
}
GeneralDataStore [,] ManagedDataStores;
This doesn't give you what you want, since it's impossible. But it give you some type safety.

Is it possible to set "this" in anonymous function?

I've got a function,
public SharpQuery Each(Action<int, HtmlNode> function)
{
for (int i = 0; i < _context.Count; ++i)
function(i, _context[i]);
return this;
}
Which calls the passed in function for each element of the context. Is it possible to set what "this" refers to inside Action<int, HtmlNode> function?
For example,
sharpQuery.Each((i, node) => /* `this` refers to an HtmlNode here */);
With a slight change in the function, you can achieve the desired effect.
public SharpQuery Each(Action<MyObject, int, HtmlNode> function)
{
for (int i = 0; i < _context.Count; ++i)
function(this, i, _context[i]);
return this;
}
Then you could write your function call like so:
sharpQuery.Each((self, i, node) => /* do something with `self` which is "this" */);
Note: The anonymous function will only have access to public members however. If the anonymous function was defined within the class, it will have access to protected and private members as usual.
e.g.,
class MyObject
{
public MyObject(int i)
{
this.Number = i;
}
public int Number { get; private set; }
private int NumberPlus { get { return Number + 1; } }
public void DoAction(Action<MyObject> action)
{
action(this);
}
public void PrintNumberPlus()
{
DoAction(self => Console.WriteLine(self.NumberPlus)); // has access to private `NumberPlus`
}
}
MyObject obj = new MyObject(20);
obj.DoAction(self => Console.WriteLine(self.Number)); // ok
obj.PrintNumberPlus(); // ok
obj.DoAction(self => Console.WriteLine(self.NumberPlus)); // error
No.
Well, yes, if the Action was created in such a scope where 'this' was available and bound in a closure -- but transparently: no.
Pass in all needed information or make sure it's captured/available in the Action itself. There are other hacks like thread-locals, etc. Best avoided.

Categories

Resources