I updated a library project method,
public static void EatFruit(string a, string b)
to
public static void EatFruit(string a, string b, bool IsEatFruit = false)
Now there are hundred of projects using this library, Do I need to update references of library dll in all projects and solutions ?
I updated the server and they all are failing by this error,
Method not found void EatFruit(System.String, System.String)'.
Do I need to update references of library dll in all projects and solutions ?
Yes. C# is a statically typed language and you've changed the method signature. You might try a slightly different refactoring approach here and just add the new functionality instead of replacing existing functionality:
public static void EatFruit(string a, string b)
{
// change the BODY of the existing method,
// but not its SIGNATURE.
EatFruit(a, b, false);
}
public static void EatFruit(string a, string b, bool IsEatFruit)
{
// move the BODY of the existing method here.
// this is a NEW method unknown to existing clients.
}
With this approach you wouldn't need to update existing clients because they can still call the same method with the same signature. New clients will also be able to call the new method, though.
Yes you need to update it there.
There is a possible solution by just making the new method overload and forcing the old one to call it.
Just do the following:
public static void EatFruit(string a, string b)
{
EatFruit(a,b,false);
}
public static void EatFruit(string a, string b, bool IsEatFruit = false)
If old projects don't need IsEatFruit parameter simply use two functions in your library project:
public static void EatFruit(string a, string b)
public static void EatFruit(string a, string b, bool IsEatFruit = false)
Even if is an optional param you will have to update the references, if you don't want to do it just create the new method.
public static void EatFruit(string a, string b)
{
}
public static void EatFruit(string a, string b, bool IsEatFruit = false)
{
}
http://en.wikipedia.org/wiki/Polymorphism_(computer_science)
Related
This question already has answers here:
CS0120: An object reference is required for the nonstatic field, method, or property 'foo'
(9 answers)
Closed 10 months ago.
Im trying to call this calculator function:
public static void Main(string[] args) {
int answer = calculate(int a, int b);
Console.WriteLine(answer);
}
public int calculate(int a, int b) {
return a + b;
}
but I keep getting an error about making a non-static reference
The reason you can't call your function is because you can't call a non static function from a static function, try adding the static keyword to your calculate function header
instance member function cannot be called from static function, so you need to make other function static aswell
public static void Main(string[] args) {
int answer = calculate(int a, int b);
Console.WriteLine(answer);
}
public static int calculate(int a, int b) {
return a + b;
}
to call it without making it static you need to create object of the class for example
class Example{
public static void Main(string[] args) {
Example example = new Example();
int answer = example.calculate(int a, int b);
Console.WriteLine(answer);
}
public int calculate(int a, int b) {
return a + b;
}
}
The static keyword means the method does not require an instance of the class in order to be invoked. For example:
MyClass.MyMethod(); // can be called without using the new keyword
Conversely, a non-static method does require an instance of the class in order to be invoked. For example:
var myInstance = new MyClass(); // create instance of class
myInstance.MyMethod(); // then call non-static method
If you think about it for a moment, you can see why a static method cannot call a non-static method. Static methods may be used when the method does not need access to instance level variables or methods. If your static method does need access to the non-static method you have 2 options:
remove the static keyword (EDIT: woops you are calling directly from main so this isn't possible in this case since main must be static. It usually is though)
make the other method static
I have a public method in a class that internally calls a particular private method within that class. It looks something like this :
public class MyClass : IMyClassInterface
{
public List<int> MyMethod(int a, int b)
{
MyPrivateMethod(a, b, ref varList, ref someVal);
}
private void MyPrivateMethod(int a, int b, ref List<int> varList, ref double someval)
{
}
}
Now, I basically want to test this public method using NUnit. I am using NMock 2.0 for mocking. How do I do it? Since, it internally calls this private method which I do not want to make public. Or is there a way to do it if I turn the private method to protected instead?
Now, I basically want to test this public method (...)
This is great. This is what you should be doing. Forget about internal details for a moment. From public method point of view, is there any difference between these two snippets?
// Your current implementation
public void MyMethod(int a, int b)
{
MyPrivateMethod(a, b);
}
private void MyPrivateMethod(int a, int b)
{
var c = a + b;
// some more code
}
// Private method inlined
public void MyMethod(int a, int b)
{
var c = a + b;
// some more code
}
Whoever calls (public) MyMethod will not be able to notice any difference between these two. End result is the same. It doesn't matter there is a private method call, because as far a public API is concerned it is irrelevant. You could inline said private method, make it gone forever, and from public consumer point of view nothing changes. End result is the only thing that's important. You test end result observable by code consumer. Not some internal gibberish.
Important realization is this:
Properly designed SOLID code will never put you in a position which will require you to do private mocking. Source of the problem? Bad design.
Source: How to mock private method - solutions
Yep. Sad but true, your design is not that great. Depending on whether you want to change that or not, there are few approaches you could take:
don't try to mock private details, focus on public API (doesn't help with design issue)
extract private method to class, introduce dependency (long-term solution, improves design and makes code easily testable)
make private method protected, override in test as suggested in other answer (doesn't help with design issue, might not yield valuable test)
Whichever you chose I leave up to you. However, I'll emphasize it one more time - mocking private method is not unit testing, library or tools problem - it is a design problem and is best solvable as such.
On a side note, (if you can) don't use NMock2. It's a library with last changes from 2009. It's like having a 30 year old car which was last serviced 15 years ago. There are much better ones nowadays (FakeItEasy, Moq, NSubstitute).
Yes the "trick" is to use protected instead of private and then inherit the class and run the test on the new class that executes the protected method.
This is a very common way to make brownfield and legacy code testable.
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
MyClassTestWrapped t = new MyClassTestWrapped();
Assert.IsTrue(t.MyPrivateMethod(...));
Assert.IsTrue(t.MyMethod(...));
MockFactory _factory = new MockFactory();
Mock<MyClassTestWrapped> mock;
mock = _factory.CreateMock<MyClass>();
mock.Expects.One.MethodWith(d => d.MyPrivateMethod()); // do the nmock magic here
}
}
public class MyClass : IMyClassInterface
{
public List<int> MyMethod(int a, int b)
{
MyPrivateMethod(a, b, ref varList, ref someVal);
}
// here change to protected
protected void MyPrivateMethod(int a, int b, ref List<int> varList, ref double someval)
{
}
}
public interface IMyClassInterface
{
}
public class MyClassTestWrapped : MyClass
{
public List<int> MyMethod(int a, int b)
{
base.MyMethod(a, b);
}
public List<int> MyPrivateMethod(int a, int b,ref List<int> varList, ref double someval)
{
base.MyPrivateMethod(a, b, ref varList, ref someval);
}
}
While currently you have to refactor your code to lose the private modifier ( wrappers and what not), You can do it fairly easy with tools Like Typemock Isolator.
I added some code to your example to write the test:
public class MyClass
{
public List<int> MyMethod(int a, int b)
{
List<int> varList = new List<int>();
double someVal = 0;
MyPrivateMethod(a, b, ref varList, ref someVal);
return varList;
}
private void MyPrivateMethod(int a, int b, ref List<int> varList, ref double someval)
{
}
}
With this straight forward approach you just fake the private method as it is in your code (no changes in the production), even it's ref parameters:
[Test]
public void TestMethod1()
{
//Arrange
var myClass = new MyClass();
var expectedVarList = new List<int> {1,2,3};
Isolate.NonPublic.WhenCalled(myClass, "MyPrivateMethod")
.AssignRefOut(expectedVarList, 0.0)
.IgnoreCall();
//Act
var resultVarList = myClass.MyMethod(0, 0);
//Assert
CollectionAssert.AreEqual(expectedVarList, resultVarList);
}
I have ScriptA with a lot of void functions:
void methodOne() {
some code
}
void methodTwo(int a, int b) {
}
I want to pass to static method of another script. Lets say it scriptB:
ScriptB.staticMethod(methodOne, some, other, primitive, parameters);
ScriptB.staticMethod(methodTwo(a, b), some, other, parameters);
The main Idea of my scripts is that ScriptB will get datas from server and call methods that got from ScriptA to make changes in my game depending on data.
I am not sure what you are trying to achieve here.
But to answer your question, you can pass methods as parameters using delegates. Here is an example:
public class ScriptA
{
public delegate void MethodOneDelegate(int a, int b);
public void MethodOne(int a, int b)
{
Console.WriteLine(a + b);
}
}
public static class ScriptB
{
public static void StaticMethod(ScriptA.MethodOneDelegate function, int a, int b)
{
function(a, b);
}
}
public static void Main()
{
ScriptA scriptA = new ScriptA();
ScriptB.StaticMethod(scriptA.MethodOne, 1, 2);
}
There is alternative solutions, you can take a look at System.Func and System.Action.
Do you need to start the methods when you put them as parameters? Or do you need the values from those methods?
Either way, you could do two things, either try this or just pass the name of the method as string and in your method check which name has been entered and start that method in your method.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
C# 4: conflicting overloaded methods with optional parameters
I just have one small research and created next code.
namespace Test {
class Program
{
public interface ITestA
{
void MethodA(int a, int b);
}
public class TestAClass : ITestA
{
public void MethodA(int a, int b)
{
Console.WriteLine("MethodA with param");
}
public void MethodA(int a, int b, bool logic = true)
{
Console.WriteLine("MethodA logic with param");
}
}
public interface ITestB
{
void MethodA(int a, int b, bool logic = true);
}
public class TestBClass : ITestB
{
public void MethodA(int a, int b)
{
Console.WriteLine("MethodB with param");
}
public void MethodA(int a, int b, bool logic = true)
{
Console.WriteLine("MethodB logic with param");
}
}
static void Main(string[] args)
{
var testA = new TestAClass();
testA.MethodA(1, 1);
var testB = new TestBClass();
testB.MethodA(1, 1);
}
} }
I have a question why compiler always choose short method with 2 parameters. And of course all this work by the same way and without Interface.
Thanks
This boils down to how the compiler treats named and optional parameters.
Check out this article at MSDN for more information, especially the paragraph Overload Resolution.
If two candidates are judged to be equally good, preference goes to a candidate that does not have optional parameters for which arguments were omitted in the call. This is a consequence of a general preference in overload resolution for candidates that have fewer parameters.
This is why in your case the compiler chooses the method without any optional parameters.
Because compiler finds a method that correspond perfectly to calling method and use that.
Compiler searches for other suitable methods if first way fails...
I made a very simple program of Delegates. I have no idea why is it showing error, even though I compared it with the one given in MSDN library, its same like the one in MSDN, still not getting compiled..the error says- "The name 'Add' does not exist in the current context "and same for the other method.. Subtract.
Please help me find what is the problem..
namespace DelegatePrac
{
public delegate void One(int a, int b);
public class Some
{
static void Add(int a, int b)
{
int c = a + b; Console.WriteLine("{0}",c);
}
static void Subtract(int a, int b)
{ int c = a - b; Console.WriteLine("{0}",c);
}
}
class Program
{
static void Main(string[] args)
{
One o1,o2;
o1 = Add;//gives error here
o2 = Subtract;//and here!!
o1(33,44);
o2(45, 15);
Console.ReadLine();
}
}
}
I was following this link- http://msdn.microsoft.com/en-us/library/ms173175.aspx
Thanks
You should see a compiler message:
The name 'Add' does not exist in the current context
which tells you that it has no clue which Add method you are talking about; Add is a static method in Some - so you need:
o1 = Some.Add;
o2 = Some.Subtract;
static methods aren't globally available; you can access static methods from the current type (and from base-types) via just their name, but if it is an unrelated type you need to qualify it with the declaring-type.
At this point it will give you a compiler error:
'DelegatePrac.Some.Add(int, int)' is inaccessible due to its protection level
which hints that it is a private method; so add public (or internal) to them:
public static void Add(int a, int b) {...}
Have you tried exchanging those two lines with errors with this?
o1 = Some.Add;
o2 = Some.Subtract;
You haven't posted your error, but the class Program has no Add or Subtract methods, so I guess your error is that Add and Subtract is not found.
EDIT
And as ssd said in his answer, the static methods have to be public to be accessed from outside the class. You have not specified any access modifier, and thereby the methods will default to private.
Two things:
You need to mark Add and Subtract as public.
They are not part of class Program. So while using them in other classes than Some, you need to specify they are part of Some by using Some.Add and Some.Subtract.
Corrected Code:
namespace DelegatePrac
{
public delegate void One(int a, int b);
public class Some
{
public static void Add(int a, int b)
{
int c = a + b; Console.WriteLine("{0}",c);
}
public static void Subtract(int a, int b)
{
int c = a - b; Console.WriteLine("{0}",c);
}
}
class Program
{
static void Main(string[] args)
{
One o1,o2;
o1 = Some.Add;//gives error here
o2 = Some.Subtract;//and here!!
o1(33,44);
o2(45, 15);
Console.ReadLine();
}
}
}