I have been working on some TDD Kata and have it nearly finished but was running into the CS1519 error. VS is telling me where the error is occurring but not sure how to go about fixing the solution. This is my first crack at doing TDD of any kind and looking for some general pointers as well.
I've been on stack overflow looking at other threads about talking about CS1519 but none of them (that I could find) seem to answer my exact question. Also, have checked out Stack Exchange for specific TDD Kata questions but needing more explanation.
using System;
using System.Linq;
namespace ChallengeCode
{
public class Calculator
{
public int Main(string number)
{
TestUnits();
if (string.IsNullOrEmpty(number))
return 0;
var numberArray = number.Replace('\n', ',').Split(',');
numberArray = NewMethod(numberArray);
NonNegValidate(numberArray);
var numberArrayInt = numberArray.Select(x => int.Parse(x)).ToArray();
return numberArrayInt.Where(x => x <= 1000).Sum(x => x);
}
private static void TestUnits()
{
throw new NotImplementedException();
}
internal static double Add(string number)
{
throw new NotImplementedException();
}
private static string[] NewMethod(string[] numberArray)
{
if (numberArray[0].StartsWith("//"))
{
var delimiter = Convert.ToChar(numberArray[0].Remove(0, 2).Distinct());
foreach (var delimiters in numberArray)
{
numberArray[1] = numberArray[1].Replace(delimiter, ',');
}
numberArray = numberArray[1].Split(',');
}
return numberArray;
}
private static void NonNegValidate(string[] numberArray)
{
if (numberArray.Any(x => int.Parse(x) < 0))
throw new Exception($"negatives not allowed {string.Join(" ", numberArray.Where(x => int.Parse(x) < 0))}");
}
}
}
Here is the code that I am using for Program.cs
using NUnit.Framework;
using System;
namespace ChallengeCode
{
class TestUnits
{
public void Add_Number_ReturnsSum(int expected, string number)
{
Assert.AreEqual(expected, Calculator.Add(number));
}
public void Add_NegNumber_Throw_An_Exception()
{
const string number = "1\n-2,-3";
var exception = Assert.Throws<Exception>(() => Calculator.Add(number));
Assert.AreEqual("negatives not allowed -2 -3", exception.Message);
}
}
}
More Details:
Screenshot of Code
I think your entry point is expecting an array instead of a single string.
I changed your code to this and it compiled. This is using the first element of your array... but has separate exceptions.
static int Main(string[] number)
{
TestUnits();
if (string.IsNullOrEmpty(number[0]))
return 0;
var numberArray = number[0].Replace('\n', ',')
.Split(',');
}
it's throwing more exceptions for being outside the bounds of this array because I'm not aware of what context this program is being used in. I assume you have another program feeding the string parameter into this one?
The Main method can be declared with or without a string[] parameter that contains command-line arguments.
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/main-and-command-args/
Related
I have a class whose method I want to invoke dynamically. But I am not able to do it. Am I missing something?
public class P_WATER
{
private int[] jDS = new int[20];
private int n;
public int[] JDS { get => jDS; set => jDS = value; }
public int N { get => n; set => n = value; }
public void P_WATER1()
{
//something...
}
}
public class Test
{
P_WATER P_WATERState1 = new P_WATER();
PLibStateList.Add(P_WATERState1);
// Try to invoke methods from each objects.
foreach (object item in StateUtility.PLibStateList)
{
Type objType= item.GetType();
objType.InvokeMember(objType.Name + "1", BindingFlags.InvokeMethod, null, item, null);
}
}
When trying to invoke the method I am getting the following exception:
Could not load file or assembly 'System.Runtime, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.
But my assembly is well bound to the project.
I've tried the same code (with little modifications) in VS2019 (Console App) and worked just fine... weird... check the using statements for ambiguity (just in case):
using System;
using System.Collections.Generic;
using System.Reflection;
My full code:
using System;
using System.Collections.Generic;
using System.Reflection;
namespace cant_dynamically_invoke_a_method_in_c_sharp
{
class Program
{
static void Main(string[] args)
{
Test.InvokeStuff();
}
}
public class P_WATER
{
private int[] jDS = new int[20];
private int n;
public int[] JDS { get => jDS; set => jDS = value; }
public int N { get => n; set => n = value; }
public void P_WATER1()
{
//something...
Console.WriteLine("Success!");
}
}
public class Test
{
public static void InvokeStuff()
{
// Needed to mock this up
List<P_WATER> PLibStateList = new List<P_WATER>();
P_WATER P_WATERState1 = new P_WATER();
PLibStateList.Add(P_WATERState1);
// Try to invoke methods from each objects.
foreach (object item in PLibStateList)
{
Type objType = item.GetType();
objType.InvokeMember(objType.Name + "1", BindingFlags.InvokeMethod, null, item, null);
}
}
}
}
Entered the method successfuly:
Regards!
i am using this code
//Rextester.Program.Main is the entry point for your code. Don't change it.
//Compiler version 4.0.30319.17929 for Microsoft (R) .NET Framework 4.5
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Reflection;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
new Program().DoTest();
}
public void DoTest()
{
var a = LoggingAdvice<asd>.Create(new a());
a.targetMethod("nadeem", 123, null);
}
}
public class LoggingAdvice<T> : DispatchProxy
{
private T _decorated;
protected override object Invoke(MethodInfo targetMethod, object[] args)
{
var result = targetMethod.Invoke(_decorated, args);
var resultTask = result as Task;
return result;
}
public static T Create(T decorated)
{
object proxy = Create<T, LoggingAdvice<T>>();
((LoggingAdvice<T>)proxy).SetParameters(decorated);
return (T)proxy;
}
private void SetParameters(T decorated)
{
if (decorated == null)
{
throw new ArgumentNullException(nameof(decorated));
}
_decorated = decorated;
}
}
public class asd
{
public asd()
{
}
public int targetMethod(string name, int number, int? count)
{
Console.WriteLine(name);
Console.WriteLine(number);
Console.WriteLine(count.HasValue ? count.Value.ToString() : "NULL");
return 1;
}
}
}
the most important thing about it, is this line of code
var result = targetMethod.Invoke(_decorated, args);
the target method has 3 parameters, one of them is nullable integer as the following
public int targetMethod(string name, int number, int? count)
the args that is getting passed to Invoke method has the following values as you can view it in the visual studio debugging mode:
["nadeem", 123, (null)]
the invoke is raising an exception that i cannot convert string to nullable integer.
how i can avoid this type of issue, note that i am not sure which function i am going to be invoked, i would only know it on runtime.
I have class: class_getanswer and class: class_performaction
in class_getanswer i have method:
class class_getanswer
{
static public int capacity()
{
Random block = new Random();
int beta = block.Next(1, 8);
return beta;
}
}
in class with method Main i want that answer to be in function if:
class class_performaction
{
static void Main()
{
int value = 5;
if(class_getanswer.capacity() < value)
{
Console.WriteLine("bla bla bla");
}
}
}
but i get that "if" doesn't exist in this context, why?
There is screenshot of kinda full programm but in different language (lithuanian): https://www.dropbox.com/s/jggwgt738vltawx/functionswt.PNG?dl=0
Please check the case of, if statement. I believe you wrote If(with a capital 'I'), change it to small case 'i'.
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.
So I have this recursive factorial function in c#. I am using it to deal with BigInteger. The problem arises when I want to deal with large integers and because my function is recursive it will cause a StackOverflow exception. Now the simple solution is to not make the function recursive. I am wondering if there is a way to get around this? I'm thinking along the lines of more ram allocated the the stack?
BigInteger Factorial(BigInteger n)
{
return n == 1 ? 1 : n * Factorial(n - 1);
}
I understand it is nice if you could express recursive functions in c# without worrying about the stack. But unfortunately that is not directly possible, and no matter how big you make the stack there will always be situations where you run out of stack space. Furthermore your performance will likely be pretty horrendous. If you have a tail recursive function like this factorial something can be done, that pretty much lets you express your function in the original recursive way, without the huge penalty.
Unfortunately c# does not directly support tail recursive calls, but workarounds are possible using a so-called "trampoline" construction.
See for example: http://bartdesmet.net/blogs/bart/archive/2009/11/08/jumping-the-trampoline-in-c-stack-friendly-recursion.aspx and http://www.thomaslevesque.com/2011/09/02/tail-recursion-in-c/
From the last blog, comes the following code that will allow you to perform the factorial as a tail recursive function without stack problems.
public static class TailRecursion
{
public static T Execute<T>(Func<RecursionResult<T>> func)
{
do
{
var recursionResult = func();
if (recursionResult.IsFinalResult)
return recursionResult.Result;
func = recursionResult.NextStep;
} while (true);
}
public static RecursionResult<T> Return<T>(T result)
{
return new RecursionResult<T>(true, result, null);
}
public static RecursionResult<T> Next<T>(Func<RecursionResult<T>> nextStep)
{
return new RecursionResult<T>(false, default(T), nextStep);
}
}
public class RecursionResult<T>
{
private readonly bool _isFinalResult;
private readonly T _result;
private readonly Func<RecursionResult<T>> _nextStep;
internal RecursionResult(bool isFinalResult, T result, Func<RecursionResult<T>> nextStep)
{
_isFinalResult = isFinalResult;
_result = result;
_nextStep = nextStep;
}
public bool IsFinalResult { get { return _isFinalResult; } }
public T Result { get { return _result; } }
public Func<RecursionResult<T>> NextStep { get { return _nextStep; } }
}
class Program
{
static void Main(string[] args)
{
BigInteger result = TailRecursion.Execute(() => Factorial(50000, 1));
}
static RecursionResult<BigInteger> Factorial(int n, BigInteger product)
{
if (n < 2)
return TailRecursion.Return(product);
return TailRecursion.Next(() => Factorial(n - 1, n * product));
}
}
You can create a new thread with the stacksize you want...
var tcs = new TaskCompletionSource<BigInteger>();
int stackSize = 1024*1024*1024;
new Thread(() =>
{
tcs.SetResult(Factorial(10000));
},stackSize)
.Start();
var result = tcs.Task.Result;
But as mentioned in comments, an iterative way for this would be better..