Difficulty regarding passing constructor parameters - c#

This is an assignment for a class.
Here is my code so far.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Proj03
{
class MyClass
{
public string MyClass(bool First, int Last)
{
if (First == true)
{
return "FirstName";
}
else if (Last == 3)
{
return "LastName";
}
}
}
class Program
{
static void Main(string[] args)
{
bool var1 = true;
int var2 = 3;
Console.WriteLine(new MyClass(var1)); //Line 34
Console.WriteLine(new MyClass(var2)); //Line 35
Console.WriteLine("Press any key to terminate.");
Console.ReadKey();
}//end main
}//end class Program
}//end namespace
The problem I'm having is twofold:
First, the error on line 34 and 35 keeps saying that there is no constructor in "MyClass" that takes one argument. So it's easy to deduce that, wow, I need a constructor that can take one argument in the class. I can make the constructor just fine, but the difficulty is in passing the "var1" and "var2". I believe I need to pass by reference here.
Secondly, I believe I need to take into consideration the fact that "var1" and "var2" are different variable types. This I really don't know what to do about. But the main question of this post is figuring out the first problem.
The limitation put on us by the instructor is that we are not allowed to change anything within the "Program" class.
The required output is as follows:
Display your first name here
Display your last name here
Press any key to terminate.

You can address the missing constructor issue like this:
public MyClass(bool First)
{
// your code here
}
public MyClass(int Last)
{
// your code here
}
Note that there is no return type specified, as constructors don't have returns. This will allow your constructor calls to run successfully.

I probably shouldn't be doing that, but, well... is this what you're trying to achieve?
class MyClass
{
private bool? _first;
private int? _last;
public MyClass(bool first)
{
_first = first;
}
public MyClass(int last)
{
_last = last;
}
public override string ToString()
{
if (_first != null)
return "FirstName";
if (_last != null)
return "LastName";
return String.Empty;
}
}

The problem is arising from the fact that you have your class name and method named the same. You cannot do this. Any properties or methods in your class must not be called the same as your class.
Your constructor issue is due to you calling new MyClass(var1). You did not specify a constructor in your class. That would look something like this:
public class MyClass
{
// This is a constructor that takes a parameter.
public MyClass(string myString)
{
}
// This is a constructor that takes 0 parameters.
// This exists if you do not specifically declare a constructor.
public MyClass()
{
}
}

What you are looking for here is called constructor overloading. You should make one constructor that accepts a bool as an argument and another that accepts an int.
It is a homework assignment, so I am not going to provide a sample. However, that should be enough to get you started.
Good luck.

Have a look at optional arguments. Using them, you could assign the arguments in the constructor default values (different from what will be sent by the program). Then, your program can send over either variable type and no error will be thrown regarding incorrect number of arguments or variable types.

Related

How does multiple method calls in an if-statement work?

I am relatively new in C#.
I am trying to understand how the flowing bit of code is working.
public static int Method3()
{
//some code
If(Class1.Method1(int Variable1).Method2(Class3 Variable2))
{
//even more code
}
//some code
}
OK, now a bit of context.
This if-statement is in Method3 and Method3 is the Class Class1.
Method1 takes an Int value and returns NULL or an Class Class2.
Method2 takes a Class lets call it Class3 and it returns true or false.
So I understand for the if-statement to be valid the condition must return true or false.
Which will come from the Method2 from my understanding.
But what is Method1 doing here?
What happens with the output of Method1?
Does it have any influence to the condition?
I hope you guys can understand what I mean.
If not please ask.
It would be far easier to understand if you get an example with more meaninful names.
Warning: This code and the one in your question is vulnerable to NullReferenceException. If GetClient returns null, you will have an exception.
For example:
public static bool SellingExample1()
{
int clientId = 21;
// Possible NullReferenceException
if(Shop.GetClient(clientId).OwesMoney())
{
// Send warning email to sales manager
}
// Do selling logic
}
public static bool SellingExample2()
{
int clientId = 21;
Client clientToSell = Shop.GetClient(clientId);
if (clientToSell == null) return false; // Check to avoid NullReferenceException before calling methods on a null object.
bool clientOwesMoney = clientToSell.OwesMoney();
if(clientOwesMoney)
{
// Send warning email to sales manager
}
// Do selling logic
}
public class Shop
{
public static Client GetClient(int clientId)
{
// Look the database and return the client
}
}
public class Client
{
public int Id { get; set; }
public string Name { get; set; }
public bool OwesMoney()
{
// Return true if there are unpaid bills
}
}
A method doesn't take a class. It takes an instance of a class.
Think of a class as a description of a thing and an instance as a specific thing of that kind, e.g. Cat might be a class where "Tom the cat" might be an instance.
The picture is a little more complex because methods can be static meaning they belong with the class or not, meaning they belong with the instance. In the following, I'll assume you are dealing with static methods because the method in your example is static.
Because you are chaining method calls, I assume Method1 returns something (an object instance) you can call Method2 on.
Now let's look at how your code might be modified given that understanding:
public static int Method3()
{
//some code
int Variable1 = 42;
Class3 Variable2 = new Class3();
if(Class1.Method1(Variable1).Method2(Variable2))
{
//even more code
}
//some code
}

Get property name C#

I have a class :
class Sample
{
...
}
and define a property like this:
Sample sampleParam =new Sample(...);
and have a function :
private void Func(Sample s)
{}
and use it like:
Func(sampleParam);
can I get the 's' name in the function? I mean can I get "sampleParam"(the name of param)?
It sounds odd; but I need the name of the passed param.
and sorry for this type of asking; I just wanted to ask my question as simple as possible
public string GetParamName(System.Reflection.MethodInfo method,int index)
{
string strParameterName = string.Empty;
if (method != null && method.GetParameters().Length > index)
strParameterName = method.GetParameters()[index].Name;
return retVal;
}
Yes there is a way to achieve this through Reflection...
You should never reference variable or property names from called methods - it's bad manners and bad design (mostly the latter).
There is nameof operator in C# 6.0, but it wasn't designed for this.
You could use expression trees, which would slightly change your syntax. If sampleParam is not a property but a variable, you can't really access it, because compiler does not store any references to that name in generated dll file.
This isn't exactly what you're asking for, but is perhaps closer to what you want, but you could take a look at System.Environment.StackTrace.
I think it is not possible to get the name for a variable which value is passed to a method. But there is the compiler service CallerMemberNameAttribute which copies the name of the caller method (here the get accessor of our property Name) to the calling method if not specified:
class Person {
static void Main(string[] args) {
Person bart = new Person();
bart.Name = "Bart";
Console.ReadKey();
}
private string _name;
public string Name {
get {
return _name;
} set {
_name = value;
PropertyChanged(); //no need to fill in `Name` here! :)
}
}
//automatically copy caller's name to `propertyName`, at compile time
private void PropertyChanged([CallerMemberName] string propertyName = "") {
object propertyValue = this.GetType().GetProperty(propertyName).GetValue(this);
Console.WriteLine("Property '" + propertyName + "' changed the value to '" + propertyValue + "'");
}
}
Prints:
Property 'Name' changed the value to 'Bart'
If you mean can you get the name 'sampleParam' from INSIDE func? The the answer is no. There is nameof() in C#6.0 but 'sampleParam' inside not in scope inside the func. The variable s (of type Sample) is crated and assigned a ref to sampleParam.
You can get the name "s" inside Func.
You can get the name "sampleParam" in the calling class (outside Func).
Example (available on dotnetfiddle)
using System;
public class Program
{
public static Sample sampleParam {get; set;} =new Sample();
public static void Main()
{
Console.WriteLine($"Name of property: {nameof(sampleParam)}");
Func(sampleParam);
}
private static void Func(Sample s)
{
Console.Write($"Name of parameter: {nameof(s)}");
}
}
public class Sample
{
}
Output:
Name of property: sampleParam
Name of parameter: s
Now this is a rather simplistic example. Func exists in the same class as sampleParam and there is only one property so one could derive the name but my assumption is despite your question stating it this way you are looking for a more generalized solution. The problem is that inside func the calling parameter name is not in scope. You could capture it via nameof in the calling method and pass it into func but you shouldn't that would be horrible code for a variety of reasons.
As described what you are doing is intentionally building fragile tightly coupled code which is something developers work very hard to prevent. The caller is not going to know the name of the parameter passed into func is important and shouldn't. This leads me to believe this an xy problem.

C# Get property value without creating instance?

Is it possible to get value without creating an instance ?
I have this class:
public class MyClass
{
public string Name{ get{ return "David"; } }
public MyClass()
{
}
}
Now I need get the value "David", without creating instance of MyClass.
Real answer: no. It's an instance property, so you can only call it on an instance. You should either create an instance, or make the property static as shown in other answers.
See MSDN for more information about the difference between static and instance members.
Tongue-in-cheek but still correct answer:
Is it possible to get value without creating an instance ?
Yes, but only via some really horrible code which creates some IL passing in null as this (which you don't use in your property), using a DynamicMethod. Sample code:
// Jon Skeet explicitly disclaims any association with this horrible code.
// THIS CODE IS FOR FUN ONLY. USING IT WILL INCUR WAILING AND GNASHING OF TEETH.
using System;
using System.Reflection.Emit;
public class MyClass
{
public string Name { get{ return "David"; } }
}
class Test
{
static void Main()
{
var method = typeof(MyClass).GetProperty("Name").GetGetMethod();
var dynamicMethod = new DynamicMethod("Ugly", typeof(string),
Type.EmptyTypes);
var generator = dynamicMethod.GetILGenerator();
generator.Emit(OpCodes.Ldnull);
generator.Emit(OpCodes.Call, method);
generator.Emit(OpCodes.Ret);
var ugly = (Func<string>) dynamicMethod.CreateDelegate(
typeof(Func<string>));
Console.WriteLine(ugly());
}
}
Please don't do this. Ever. It's ghastly. It should be trampled on, cut up into little bits, set on fire, then cut up again. Fun though, isn't it? ;)
This works because it's using call instead of callvirt. Normally the C# compiler would use a callvirt call even if it's not calling a virtual member because that gets null reference checking "for free" (as far as the IL stream is concerned). A non-virtual call like this doesn't check for nullity first, it just invokes the member. If you checked this within the property call, you'd find it's null.
EDIT: As noted by Chris Sinclair, you can do it more simply using an open delegate instance:
var method = typeof(MyClass).GetProperty("Name").GetGetMethod();
var openDelegate = (Func<MyClass, string>) Delegate.CreateDelegate
(typeof(Func<MyClass, string>), method);
Console.WriteLine(openDelegate(null));
(But again, please don't!)
You can make that property static
public static string Name{ get{ return "David"; } }
Usage:
MyClass.Name;
You requirements do seem strange, but I think you're looking for some kind of metadata. You can use an attribute to achieve this:
public class NameAttribute : Attribute {
public string Name { get; private set; }
public NameAttribute(string name) {
Name = name;
}
}
[Name("George")]
public class Dad {
public string Name {
get {
return NameGetter.For(this.GetType());
}
}
}
[Name("Frank")]
public class Son : Dad {
}
public static class NameGetter {
public static string For<T>() {
return For(typeof(T));
}
public static string For(Type type) {
// add error checking ...
return ((NameAttribute)type.GetCustomAttributes(typeof(NameAttribute), false)[0]).Name;
}
}
Now this code can get names with and without instances:
Console.WriteLine(new Dad().Name);
Console.WriteLine(new Son().Name);
Console.WriteLine(NameGetter.For<Dad>());
Console.WriteLine(NameGetter.For<Son>());
You can make your property static, as pointed out by many others.
public static string Name{ get{ return "David"; } }
Be aware that this means your instances of MyClass will no longer have their own Name property, since static members belong to the class, not the individual object instances of it.
Edit:
In a note, you mentioned that you want to override the Name property in subclasses. At the same time, you want to be able to access it at the class level (access it without creating an instance of your class).
For the static properties, you would simply create a new Name property in each class. Since they are static, you're always (almost always, yay reflection) going to access them using a specific class, so you'd be specifying which version of Name you want to get. If you want to try and hack polymorphism in there and get the name from any given subclass of MyClass, you could do so using reflection, but I wouldn't recommend doing so.
Using the example from your comment:
public class Dad
{
public static string Name { get { return "George"; }
}
public class Son : Dad
{
public static string Name { get{ return "Frank"; }
}
public static void Test()
{
Console.WriteLine(Dad.Name); // prints "George"
Console.WriteLine(Son.Name); // prints "Frank"
Dad actuallyASon = new Son();
PropertyInfo nameProp = actuallyASon.GetType().GetProperty("Name");
Console.WriteLine(nameProp.GetValue(actuallyASon, null)); // prints "Frank"
}
As a side note, since you are declaring a property that has only a getter and it is returning a constant value, I recommend possibly using a const or static readonly variable instead.
public const string Name = "David";
public static readonly string Name = "David";
Usage for both would be the same:
string name = MyClass.Name;
The main benefit (and drawback) of const is that all references to it are actually replaced by its value when the code is compiled. That means it will be a little faster, but if you ever change its value, you will need to recompile ALL code that references it.
Whenever you write C# code, always check if your method and property getter/setter code does anything at all with other instance members of the class. If they don't, be sure to apply the static keyword. Certainly the case here, it trivially solves your problem.
The reason I really post to this question is that there's a bit of language bias at work in some of the answers. The C# rule that you can't call an instance method on a null object is a specific C# language rule. It is without a doubt a very wise one, it really helps to troubleshoot NullReferenceExceptions, they are raised at the call site instead of somewhere inside of a method where it gets very hard to diagnose that the this reference is null.
But this is certainly not a requirement to the CLR, nor of every language that run on the CLR. In fact, even C# doesn't enforce it consistently, you can readily bypass it in an extension method:
public static class Extensions {
public static bool IsNullOrEmpty(this string obj) {
return obj != null && obj.Length > 0;
}
}
...
string s = null;
bool empty = s.IsNullOrEmpty(); // Fine
And using your property from a language that doesn't have the same rule works fine as well. Like C++/CLI:
#include "stdafx.h"
using namespace System;
using namespace ClassLibrary1; // Add reference
int main(array<System::String ^> ^args)
{
MyClass^ obj = nullptr;
String^ name = obj->Name; // Fine
Console::WriteLine(name);
return 0;
}
Create a static property:
public class MyClass
{
public static string Name { get { return "David"; } }
public MyClass()
{
}
}
Get it like so:
string name1 = MyClass.Name;
That is not possible. As Name is an instance property, you can only get its value if you have an instance.
Also, note that you are not talking about a parameter, but about a property.
Create a static class or a static property, and you don't have to explicitly instantiate it.

Passing an Enum as an argument

I am playing around with trying to make a simple Roguelike game to learn C# a bit better. I am trying to make a general method that I can give it an Enum as an argument, and it will return how many elements are in that Enum as an int. I need to make it as general as possible, because I will have several different classes calling the method.
I have searched around for the last hour or so, but I couldn't find any resources here or otherwise that quite answered my question... I'm still at a beginner-intermediate stage for C#, so I am still learning all the syntax for things, but here is what I have so far:
// Type of element
public enum ELEMENT
{
FIRE, WATER, AIR, EARTH
}
// Counts how many different members exist in the enum type
public int countElements(Enum e)
{
return Enum.GetNames(e.GetType()).Length;
}
// Call above function
public void foo()
{
int num = countElements(ELEMENT);
}
It compiles with the error "Argument 1: Cannot convert from 'System.Type' to 'System.Enum'". I kind of see why it won't work but I just need some direction to set everything up correctly.
Thanks!
PS: Is it possible to change the contents of an enum at runtime? While the program is executing?
Try this:
public int countElements(Type type)
{
if (!type.IsEnum)
throw new InvalidOperationException();
return Enum.GetNames(type).Length;
}
public void foo()
{
int num = countElements(typeof(ELEMENT));
}
You could also do this with a generic method. Personally I like the syntax better for the foo() method this way, since you don't have to specify typeof()
// Counts how many different members exist in the enum type
public int countElements<T>()
{
if(!typeof(T).IsEnum)
throw new InvalidOperationException("T must be an Enum");
return Enum.GetNames(typeof(T)).Length;
}
// Call above function
public void foo()
{
int num = countElements<ELEMENT>();
}

Property is null, even after being set in code

I've been trying to solve this for ages (3 days) now and I just cannot figure it out. I will try to explain the problem comprehensively because it is a bit more complex.
My school assignment is to create a simple text game using OOP in C# Visual Studio 2008 (should be built on a library the teacher provided for us). It should only use console. I have a decent experience with OOP from PHP and C++ but I still cannot figure this out.
80% of the text game is already working so I won't bore you with classes and stuff that already works and is not related to the problem. Ok let's get started:
Each command in the game (what you can type into the console and hit enter) is represented by a single class both extending an abstract class and an interface from the library I am supposed to built the game on. Bellow is a class Use which represents a command for using items (e.g. you type "use sword" into the console and the game will look for an item called sword and call its use method):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Game.Commands
{
class Use : TextGame.Commands.ACommand, TextGame.Commands.ICommand
{
private string name;
public new string Name
{
set { this.name = value; }
get { return this.name; }
}
private string description;
public new string Description
{
set { this.description = value; }
get { return this.description; }
}
private string parameters;
public new string Params
{
set { this.parameters = value; }
get { return this.parameters; }
}
public Use(string name, string description) : base(name, description)
{
this.name = name;
this.description = description;
}
private TextGame.Core.GameState gameState;
public TextGame.Core.GameState Execute(TextGame.Core.IGame game)
{
// This is just a test because it appears the problem is
// with the parameters property. There should be a command
// you have typed in the console but its always null
// Note that I have not yet coded the body of this method.
// I will do that once I solve the problem.
if (this.parameters == null)
{
Console.WriteLine("is null");
}
else
{
Console.WriteLine(this.parameters);
}
return this.gameState;
}
}
}
There are two other classes that are used. The Parser class and the Game class. There are a bit longer so I will only post snippets of relevant stuff from them. Parser class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections; // ArrayList, Dictionary, Hashtable
using System.Text.RegularExpressions; // regex engine
using Game.Commands;
namespace Game
{
class Parser
{
private ArrayList commands = new ArrayList();
// All commands that are available in the game so far are
// initialized here in the constructor (and added to the arraylist)...
// skip to the other method this is not important
public Parser()
{
this.commands.Add(new North("^north", "Go north"));
this.commands.Add(new South("^south", "Go south"));
this.commands.Add(new East("^east", "Go east"));
this.commands.Add(new West("^west", "Go west"));
this.commands.Add(new Use("^use\\s\\w+", "Try to use the selected item"));
this.commands.Add(new Quit("^quit", "Quit the game"));
}
// This method takes as an argument a string representing
// a command you type in the console. It then searches the arraylist
// via the regex. If the command exists, it returns an the command object
// from the arraylist
// This works fine and returns right objects (tested)
public TextGame.Commands.ACommand GetCommand(string command)
{
TextGame.Commands.ACommand ret = null;
foreach (TextGame.Commands.ACommand c in this.commands)
{
Regex exp = new Regex(#c.Name, RegexOptions.IgnoreCase);
MatchCollection MatchList = exp.Matches(command);
if (MatchList.Count > 0)
{
ret = c;
}
}
return ret;
}
}
}
Now a snippet from the Game class where I'm using both above classes:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TextGame.Core;
using System.Collections;
using Game.Items;
using Game.Commands;
namespace Game
{
class Game : TextGame.Core.IGame
{
public void Play()
{
// Here I read commands from the console in a loop and
// call the ProcessCommand() method. No problem here.
while (true)
{
string command = Console.ReadLine();
this.ProcessCommand(command);
}
}
// This is the IMPORTANT method so take a closer look
private TextGame.Core.GameState gameState;
public TextGame.Core.GameState ProcessCommand(string command)
{
Parser parser = new Parser();
TextGame.Commands.ACommand c = parser.GetCommand(command);
if (c != null)
{
// HERE I ADD THE COMMAND FROM THE CONSOLE TO THE C OBJECT
// I ADD IT VIA THE SETTER TO THE PARAMETERS PROPERTY
// OF THE COMMAND
c.Params = command;
// AND I CALL THE COMMAND'S EXECUTE() METHOD - SEE THE FIRST CLASS -
// USE - WHERE I TEST FOR THE PARAMS PROPERTY BUT IT IS STILL NULL
this.gameState = ((TextGame.Commands.ICommand)c).Execute(this);
}
}
}
}
I have added comments to the snippets to describe where is the problem. I hope I have explained it well.
Anyone has any ideas? I've been working on this projects for about 3 weeks now and most of the stuff went smoothly when 3 days ago I came across this problem and since then I've been trying to get my head around this problem.
Your problem is with the 'new' keyword. Here's where you're using it in the 'Use' class:
private string parameters;
public new string Params
{
set { this.parameters = value; }
get { return this.parameters; }
}
You're creating a different property that just happens to have the same name as a property on the type you are inheriting from. The 'new' keyword tells the compiler you meant to do that.
Basically, this means that if you do the following:
var x = new Use();
x.Params = "abcd";
((ACommand)x).Params = "wxyz";
Console.Writeline("direct: " + x.Params);
Console.Writeline("ACommand: " + ((ACommand)x).Params);
You'll get this output:
direct: abcd
ACommand: wxyz
You probably want to remove the definition of 'Params' entirely from Use and just inherit the one from ACommand. Probably from Name and Description as well, but you should be able to figure out from here if you want that or not.
Without seeing the code for the ACommand class... Try removing the "new" operator in the Params declaration of the Use class. When your setting the property c.Params = command; is actually setting the property of the base class, in the Execute method your checking this.parameters instead of base.Params.
// This is just a test because it appears the problem is
// with the parameters property. There should be a command
// you have typed in the console but its always null
// Note that I have not yet coded the body of this method.
// I will do that once I solve the problem.
This is caused by you declaring new on your properties. These should be override, or not included at all if you don't need to change the logic of ACommand.
When you reference as an ACommand:
TextGame.Commands.ACommand c = parser.GetCommand(command);
c.Params = command;
You will use either ACommand's Params, or your overrides (if you had defined one).
Your new Params shadow ACommand's Params, and are only accessible if your reference is a UseCommand.
Your problem is here:
private string parameters;
public new string Params
{
set { this.parameters = value; }
get { return this.parameters; }
}
In your code:
c.Params = command;
you are referencing the type TextGame.Commands.ACommand. Because you're hiding the Param property in your subclass, you're causing a non-polymorphic reference. Remove the definition above and rely on the base class definition of Param, and you'll be fine.
It's been a while since I ran into this problem, but if you open that up in Reflector I expect you will see that you are hiding the Use.Params property behind a callvirt explicitly bound to its base type there.... as the faster typists pointed out.

Categories

Resources