I am trying to learn C# and I am up to an example that uses a boolean. For the life of me I cant figure out why the program isnt noticing that I am trying to pass a value of true to the boolean. Here is the code in the Form.cs:
namespace WindowsFormsApplication7
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button2_Click(object sender, EventArgs e)
{
HappyBirthday birthdayMessage = new HappyBirthday();
string returnedMessage;
birthdayMessage.PresentCount = 5;
birthdayMessage.MyProperty = "Adam";
birthdayMessage.hasParty = true;
returnedMessage = birthdayMessage.MyProperty;
MessageBox.Show(returnedMessage);
}
}
}
Here is the Class that I created:
class HappyBirthday
{
//====================
// CLASS VARIABLES
//====================
private int numberOfPresents;
private string birthdayMessage;
private bool birthdayParty;
//===========================
// DEFAULT CONSTRUCTOR
//===========================
public HappyBirthday()
{
numberOfPresents = 0;
//birthdayParty = false;
}
//===========================
// METHOD
//===========================
private string getMessage(string givenName)
{
string theMessage;
theMessage = "Happy Birthday " + givenName + "\n";
theMessage += "Number of presents = ";
theMessage += numberOfPresents.ToString() + "\n";
if (birthdayParty == true)
{
theMessage += "Hope you enjoy the party!";
}
else
{
theMessage += "No party = sorry!";
}
return theMessage;
}
//================================
// READ AND WRITE PROPERTY
//================================
public string MyProperty
{
get { return birthdayMessage; }
set { birthdayMessage = getMessage(value); }
}
//================================
// WRITE-ONLY PROPERTY
//================================
public int PresentCount
{
set { numberOfPresents = value; }
}
public bool hasParty
{
set { birthdayParty = value; }
}
}
Now I set the initial value to false (even though if my understanding is correct that should be the default value), but when I try to set it = true, the program does not recognize it. Am I supposed to pass a boolean differently then I would a string or int?
You're setting MyProperty before you're setting hasParty. getMessage() is not being called every time MyProperty is polled.
The way MyProperty works is confusing, because the set and get deal with different values (you set the name, and then get the whole message, which is confusing). I'd replace it with a GivenName property and then make the GetMessage() (or expose it as a read-only property Message) public.
Also, you can make your code much simpler by using auto-properties (you can use private gets to keep the write-only behavior, though in the real world write-only properties are very rare, and you should probably just make them public like the sets). And since the default int value is 0, you don't need to specify your default constructor. Here's how the code looks now:
class HappyBirthday
{
public string Message
{
get
{
string theMessage;
theMessage = "Happy Birthday " + GivenName + "\n";
theMessage += "Number of presents = ";
theMessage += PresentCount.ToString() + "\n";
if (HasParty)
{
theMessage += "Hope you enjoy the party!";
}
else
{
theMessage += "No party = sorry!";
}
return theMessage;
}
}
public string GivenName { private get; set; }
public int PresentCount { private get; set; }
public bool HasParty { private get; set; }
}
Related
Hi I am a little new in programming in C#, and I am a little stuck. I have tried searching this site, but I have not been successful on finding an answer to my question. I have also tried changing my private to a public but that did not work.
Here is the error message I am getting:
Error 2 Inconsistent accessibility: parameter type 'exam2.location' is
less accessible than method
'exam2.Form1.MoveToANewLocation(exam2.location)'
Here is part of my code:
public Form1()
{
IntializeComponent();
CreateObject();
MoveToANewLocation(livingRoom);
}
private void MoveToANewLocation(location newLocation)
{
currentLocation = newLocation;
comboBox1.Items.Clear();
for (int i = 0; i < currentLocation.Exits.Length; i++)
{
comboBox1.Items.Add(currentLocation.Exits[i].Name);
comboBox1.SelectedIndex = 0;
}
textBox1.Text = currentLocation.Description;
if (currentLocation is IHasExteriorDoor)
{
GoThroughTheDoor.Visible = true;
}
else
{
GoThroughTheDoor.Visible = false;
}
}
abstract class location
{
public location(string name)
{
this.name = name;
}
public location[] Exits;
private string name;
public string Name
{
get { return name; }
}
public virtual string Description
{
get {
string description = "You're standing in the" + name +
". You see exits to the following places: ";
for (int i = 0; i < Exits.Length; i++)
{
description += " " + Exits[i].Name;
if (i != Exits.Length - 1)
description += ",";
}
description += ",";
return description;
}
}
}
Make location class public if it's not public already
You need to declare your class this way:
public abstract class location
{
...
}
As an aside, general code style has classes starting with a capital letter (ie. Location).
C# defaults the accessibility to internal, so having public methods inside the class will cause this error (like your constructor, properties, and virtual method). A good rule of thumb is to always declare classes public unless you know for sure you want everything in them to be internal or lower.
See MSDN for more information on access modifiers.
i make user control from 3 text boxes but i don not how to declare read only property to it i tried many things but it do not work here is my code to make the control
i want to make it read only when needed like if i add checkbox i want if checkbox.check=true make my control readonly
public partial class dateIN : UserControl
{
Dates datess = new Dates();
public dateIN()
{
InitializeComponent();
}
private void dateIN_Leave(object sender, EventArgs e)
{
if (txtDay.Text != "" || txtMonth.Text != "" || txtYear.Text != "")
{
if (!datess.IsHijri(txtDay.Text.Trim() + "/" + txtMonth.Text.Trim() + "/" + txtYear.Text.Trim()))
{
txtDay.Focus();
}
}
}
public string Day
{
set { txtDay.Text = value; }
get { return txtDay.Text; }
}
public string Month
{
set { txtMonth.Text = value; }
get { return txtMonth.Text; }
}
public string Year
{
set { txtYear.Text = value; }
get { return txtYear.Text; }
}
need to know how to make read only property available here plz
just remove the set { } part of the property
Example:
public string Day
{
get { return txtDay.Text; }
}
I dont know the correlation of where your "txtDay", "txtMonth", "txtYear" come from, but you could do something like
public partial class dateIN : UserControl
{
...
...
private bool AllowEditing()
{ return SomeCondition when SHOULD be allowed...; }
public string Day
{
// only allow the set to apply the change if the "AllowEditing" condition
// is true, otherwise, ignore the attempt to assign.
set { if( AllowEditing() )
txtDay.Text = value; }
get { return txtDay.Text; }
}
// same concept for month and year too
}
so may you add some flag to your set when it is true then you set a value.
also you can work with textbox property called ReadOnly.
I have a bunch of business class with autoproperties :
public class A {
public int Id { get; set; }
public string Title { get; set;}
}
Because the application evolves, there is a new requirement to enable tracking the changes of the properties, in order to send to the backing store only changed data.
In order to reach this goal, I have to convert ALL properties to field + property like this :
public class A {
private int m_Id;
public int Id {
get { return m_Id; }
set {
if(m_Id != value){
SetChanged("Id");
m_Id = value;
}
}
}
private string m_Title;
public string Title
{
get { return m_Title; }
set {
if(m_Title != value){
SetChanged("Title");
m_Title = value;
}
}
}
protecte void SetChanged(string propertyName) {
// Not important here
}
}
Is there a way to quickly refactor my code to avoid having to manually change the properties ?
There's no way in the IDE to do this, but if you need to replace all X properties, I would write a short console application to do it.
The process would be:
Iterate over all files in directory matching *.cs
Foreach file, regex find and replace old property for new property syntax
Using regex to match is very powerful. Regex can be used in VS2010 to do a find/replace operation. If you try finding this (with regex enabled)
{(public|private|internal|protected)}:b{[a-zA-Z0-9]+}
:b{[a-zA-Z0-9]+}:b\{ get; set; \}
It will match properties like this
public Type Foo { get; set; }
In your console application find all lines of code that match the above, then start splitting them up into Modifier, Type, Property Name and finally replacing the whole block with something like this
// PS: this is pseudocode ;-) or could be your new property template
private [Type] m_[PropertyName].ToPascaleCase
public [Type] PropertyName
{
get { return m_[PropertyName].ToPascaleCase; }
set
{
if(m_[PropertyName].ToPascaleCase != value){
SetChanged([PropertyName]);
m_[PropertyName].ToPascaleCase = value;
}
}
}
Finally I would advocate taking a backup of your code or running this test offline and testing before checking in!!
You can always just create a generic method that will do the assignment and call SetChange
void SetChangeIfNeeded<T>(ref T field, T value, string propertyName)
{
if (!EqualityComparer<T>.Default.Equals(field, value))
{
field = value;
SetChanged(property);
}
}
You would still need to have a private back field. Your class would look something like:
public class A {
private int m_id
public int Id
{
get { return m_id };
set { SetChangeIfNeeded<int>(ref m_id, value, "Id"); }
}
}
ReSharper can do this, but wouldn't modify setter.
public string Title {
get { return m_title; }
set { m_title = value; }
}
There is probably no direct way of doing this with refraction. If this was my problem. I would make code to generate this:
public string MakePropertyBigger(string varName, string propName, string dataType)
{
string output = "";
output += string.Format("private {0} {1};", dataType, varName) + Environment.NewLine;
output += string.Format("public {0} {1}", dataType, propName) + Environment.NewLine;
output += "{" + Environment.NewLine;
output += string.Format("get { return {0}; }", varName) + Environment.NewLine;
output += string.Format("set { if({0} != value){ SetChanged(\"{1}\");", varName, propName) + Environment.NewLine;
output += string.Format("{0} = value; }", varName) + Environment.NewLine;
output + "}" + Environment.NewLine + "}";
Now just plug this in and chug it out.
I've got something like this in my property/accessor method of a constructor for my program.
using System;
namespace BusinessTrips
{
public class Expense
{
private string paymentMethod;
public Expense()
{
}
public Expense(string pmtMthd)
{
paymentMethod = pmtMthd;
}
//This is where things get problematic
public string PaymentMethod
{
get
{
return paymentMethod;
}
set
{
if (string.IsNullOrWhiteSpace(" "))
paymentMethod = "~~unspecified~~";
else paymentMethod = value;
}
}
}
}
When a new attribute is entered, for PaymentMethod, which is null or a space, this clearly does not work. Any ideas?
do you perhaps just need to replace string.IsNullOrWhiteSpace(" ") with string.IsNullOrWhiteSpace(value) ?
From your posted code, you need to call:
this.PaymentMethod = pmtMthd;
instead of
paymentMethod = pmtMthd;
The capital p will use your property instead of the string directly. This is why it's a good idea to use this. when accessing class variables. In this case, it's the capital not the this. that makes the difference, but I'd get into the habit of using this.
Jean-Barnard Pellerin's answer is correct.
But here is the full code, which I tested in LinqPad to show that it works.
public class Foo {
private string _paymentMethod = "~~unspecified~~";
public string PaymentMethod
{
get
{
return _paymentMethod;
}
set
{
if (string.IsNullOrWhiteSpace(value))
_paymentMethod = "~~unspecified~~";
else _paymentMethod = value;
}
}
}
With a main of:
void Main()
{
var f = new Foo();
f.PaymentMethod = "";
Console.WriteLine(f.PaymentMethod);
f.PaymentMethod = " ";
Console.WriteLine(f.PaymentMethod);
f.PaymentMethod = "FooBar";
Console.WriteLine(f.PaymentMethod);
}
Output from console:
~~unspecified~~
~~unspecified~~
FooBar
It seems that, due to an unknown cause, I am now unable to edit anything in my DataGridView. The DGV's ReadOnly property value is false, and all columns except for one all have the ReadOnly property set to false as well.
I'm beginning to think that it may be due to a special value I tried adding to one of my classes, one that I only wanted to be modified within the class, but still read only to the public. I don't think that value is messing with anything else, but none the less, here is the relevant portion of my code:
private void loaderWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
loadingBar.Value = e.ProgressPercentage;
if (e.UserState != null)
{
savefiles.Add((SaveFile)e.UserState);
}
}
Where savefiles is a BindingList, and where SaveFile is my class:
public class SaveFile
{
private string d_directory;
private int d_weirdnumber;
private bool d_isautosave;
private string d_fullname;
private string d_datatype;
private string d_owner;
private bool d_isquicksave;
private string d_title;
private string d_gametime;
public SaveFile() { }
public SaveFile(string directory, int weirdnumber, bool isautosave, string fullname, string datatype, string owner, bool isquicksave, string title)
{
d_directory = directory;
d_weirdnumber = weirdnumber;
d_isautosave = isautosave;
d_fullname = fullname;
d_datatype = datatype;
d_owner = owner;
d_isquicksave = isquicksave;
d_title = title;
}
public string Gametime
{
get { return d_gametime; }
}
public string Datatype
{
get { return d_datatype; }
set { d_datatype = value; }
}
public string Title
{
get { return d_title; }
set { d_title = value; }
}
public bool IsQuickSave
{
get { return d_isquicksave; }
set { d_isquicksave = value; }
}
public bool IsAutoSave
{
get { return d_isautosave; }
set { d_isautosave = value; }
}
public string Directory
{
get { return d_directory; }
set { d_directory = value; }
}
public string FullName
{
get { return d_fullname; }
set
{
d_fullname = value;
string[] split = value.Split(new char[]{'-'});
foreach (string str in split)
{
if (System.Text.RegularExpressions.Regex.IsMatch(str, "^\\d\\d:\\d\\d:\\d\\d$"))
{
d_gametime = str;
}
}
}
}
public int Weirdnumber
{
get { return d_weirdnumber; }
set { d_weirdnumber = value; }
}
public string Owner
{
get { return d_owner; }
set { d_owner = value; }
}
}
Gametime is that special property I mentioned earlier. It doesn't have a set function, but according to this, I should be in the clear, right?
Can anyone then tell me why I may not be able to edit any of the DGV cells?
EDIT: I just found out that not setting AutoGenerateColumns to false allows me to edit again, but I still don't know why.
After several hours, a friend finally took a look at it over Remote Desktop. He wrote a function to force all columns to have a non read-only status, and go figure, it worked. So we looked at the column properties in the editor, and somehow... I don't know why... they were all set to Read only. I swear I checked them 4 times before.
The lesson of this story (I guess): When in doubt, check your settings. When not in doubt, become doubtful. Otherwise, file a bug report to Microsoft :\