Constructor pointing to a property not accesing set keyword - c#

I'm just learning C# and trying to get some practice working with classes as opposed to writing everything in Main, so I'm trying to write a console game of hangman.
I'm initializing the guessed letter with this line:
Guess guess = new Guess(Console.ReadLine());
Which points to this constructor in the Guess.cs file:
public Guess(string guessString)
{
CurrentGuess = Convert.ToChar(guessString);
}
CurrentGuess referring to this property:
private char currentGuess
public char CurrentGuess
{
get
{
return currentGuess;
}
set
{
foreach (char letter in guessList)
{
if (letter == value)
{
GuessedAlready = true;
break;
}
}
if (GuessedAlready == false)
{
value = currentGuess;
guessesMade++;
guessList[guessesMade-1] = value;
}
}
}
When I run the program and input a char value, it isn't getting set to currentGuess. Also Visual Studio is telling me that currentGuess is never getting assigned to, and is keeping it's current value (which is blank).
Why isn't the set keyword working? I've followed the path to currentGuess over and over and I can't see it, so I'm assuming it's a reason I don't know yet.
Any help would be appreciated!

You have to swap this assingment in your setter
value = currentGuess;
into
currentGuess = value;
In the set method the value is the incoming parameter. In your case you want to store that value in your local class variable curtentGuess;

Related

C# Variable Scoping

I'm new to C#, having written a little in a CMS, but my background is mostly JavaScript related. That said, I am working in the "Scripting" client in OpenText Capture Center. When executing the code below I get the error "The Name 'srfOnly' does not exist in the current context"
If I move the variable declarations to within the function, I get the same error, If I move them to them to global I get the same error but on a different line number.
How can I access the variables srfOnly and otherDocs throughout the code?
//Parameters:
//DataPool data
//ITrace trace
// Checking if condition is fulfilled.
if (checkDocuments(data))
{
// Getting batch field named 'cc_SkipValidation'.
// Setting new value.
DOKuStar.Data.Xml.Bool skipValidationField = data.RootNode.Fields["cc_SkipValidation"] as DOKuStar.Data.Xml.Bool;
bool srfOnly = false;
bool otherDocs = false;
if(otherDocs == true)
{
skipValidationField.SetValue(false);
}
if(srfOnly == true && otherDocs == false)
{
skipValidationField.SetValue(true);
skipValidationField.State = DataState.Ok;
}
}
// !!! Closing bracket is neccessary !!!
}
// ------------------ Functions
public bool checkDocuments(DataPool dataPool)
{
foreach (Document doc in dataPool.RootNode.Documents)
{
if (doc.Name == "ServiceRequestForm")
{
srfOnly = true;
}
else if (doc.Name != "ServiceRequestForm")
{
otherDocs = true;
}
}
trace.WriteInfo("Trace info for Validation of srfOnly = " + srfOnly);
trace.WriteInfo("Trace info for Validation of otherDocs = " + otherDocs);
// !!! No closing bracket needed !!!
Variables are limited in scope by where they exist in your code. If you declare a variable within an if{} block, the variable only exists inside that block. If you declare a variable inside of a class but not within a class method, the variable is accessible to every method in the class. If you want a variable to be accessible to every class with in a project, you would normally declare it in a public static class.
For example...
public static class GlobalClass
{
public static string myGlobal="";
}
class myClass
{
string myClassVariable = "";
private void method()
{
//myGlobal is accessible using this
GlobalClass.myGlobal ="some value";
//myClassVariable is accessible here
myClassVariable = "somevalue";
if(condition)
{
//myClassVariable is also accessible here
myClassVariable = "somevalue";
string ifBlockVariable = "";
}
//ifBlockVariable is not accessible here
}
}
A variable is only accessible within the current block (and the blocks within that block). If you want to access the srfOnly variable within the checkDocuments method you can pass it as a parameter:
public bool checkDocuments(DataPool dataPool, bool srfOnly)
If you want the variable to be accessible from anywhere in the class, you can declare it as a a property of the class or an instance variable as following:
private bool _srfOnly;

Best practice how to line by line check if line contains string from array and update a class setter knowing the key

Im working on an Windows Classic Desktop application that reads a Minecraft Tekkit settings file line by line and compairs the lines up against an array with settings keys. If the string from the line contains the key the key should be removed from the string and the resulting variable should be used to update an an object's appropriate variable.
Here is the string array with the keys to look for
static string[] tekkitSettingsKeys = {
"generator-settings=",
"op-permission-level=",
"allow-nether=",
"level-name=",
"enable-query=",
"allow-flight=",
"server-port=",
"level-type=",
"enable-rcon=",
"force-gamemode=",
"level-seed=",
"server-ip=",
"max-build-height=",
"spawn-npcs=",
"white-list=",
"spawn-animals=",
"texture-pack=",
"hardcore=",
"snooper-enabled=",
"online-mode=",
"pvp=",
"difficulty=",
"gamemode=",
"player-idle-timeout=",
"max-players=",
"spawn-monsters=",
"generate-structures=",
"view-distance=",
"motd="
};
Here are the variables and the getters and setters for the TekkitServerSettings class
/*
The settings used to customize world generation. See Superflat and Customized for possible settings and examples.
*/
private string _generatorSettings = String.Empty;
/*
Sets permission level for ops.
1 - Ops can bypass spawn protection.
2 - Ops can use /clear, /difficulty, /effect, /gamemode, /gamerule, /give, and /tp, and can edit command blocks.
3 - Ops can use /ban, /deop, /kick, and /op.
4 - Ops can use /stop. DEFAULT
*/
private int _opPermissionLevel = 4;
/*
Allows players to travel to the Nether.
false - Nether portals will not work.
true - The server will allow portals to send players to the Nether.
*/
private bool _allowNether = true;
/*
The "level-name" value will be used as the world name and its folder name. You may also copy your saved game folder here, and change the name to the same as that folder's to load it instead.
Characters such as ' (apostrophe) may need to be escaped by adding a backslash before them.
*/
private string _levelName = "world";
/*
Enables GameSpy4 protocol server listener. Used to get information about server.
*/
private bool _enableQuery = false;
/*
Allows users to use flight on your server while in Survival mode, if they have a mod that provides flight installed.
With allow-flight enabled griefers will possibly be more common, because it will make their work easier. In Creative mode this has no effect.
false - Flight is not allowed (players in air for at least 5 seconds will be kicked).
true - Flight is allowed, and used if the player has a fly mod installed.
*/
private bool _allowFlight = true;
/*
Changes the port the server is hosting (listening) on. This port must be forwarded if the server is hosted in a network using NAT (If you have a home router/firewall).
*/
private int _serverPort = 25565;
/*
Determines the type of map that is generated.
DEFAULT - Standard world with hills, valleys, water, etc.
FLAT - A flat world with no features, meant for building.
LARGEBIOMES - Same as default but all biomes are larger.
AMPLIFIED - Same as default but world-generation height limit is increased.
CUSTOMIZED - Same as default unless generator-settings is set to a preset.
*/
private string _levelType = "DEFAULT";
/*
Enables remote access to the server console.
*/
private bool _enableRcon = false;
/*
Force players to join in the default game mode.
false - Players will join in the gamemode they left in.
true - Players will always join in the default gamemode.
*/
private bool _forceGameMode = false;
/*
Add a seed for your world, as in Singleplayer.
Some examples are: minecraft, 404, 1a2b3c.
*/
private string _levelSeed = String.Empty;
/*
Set this if you want the server to bind to a particular IP. It is strongly recommended that you leave server-ip blank!
Set to blank, or the IP you want your server to run (listen) on.
*/
private string _serverIp = String.Empty;
/*
The maximum height in which building is allowed. Terrain may still naturally generate above a low height limit.
*/
private int _maxBuildHeight = 256;
/*
Determines if villagers will be spawned.
true - Enabled. Villagers will spawn.
false - Disabled. No villagers.
*/
private bool _spawnNpcs = true;
/*
Enables a whitelist on the server.
With a whitelist enabled, users not on the whitelist will be unable to connect. Intended for private servers, such as those for real-life friends or strangers carefully selected via an application process, for example.
false - No white list is used.
true - The file whitelist.json is used to generate the white list.
Note: Ops are automatically white listed, and there is no need to add them to the whitelist.
*/
private bool _whiteList = false;
/*
Determines if animals will be able to spawn.
true - Animals spawn as normal.
false - Animals will immediately vanish.
Tip: if you have major lag, turn this off/set to false.
*/
private bool _spawnAnimals = true;
/*
Server-side texture packs. Provide a link to the zip file */
private string _texturePack = String.Empty;
/*
If set to true, players will be permanently banned if they die.
*/
private bool _hardcore = false;
/*
Sets whether the server sends snoop data regularly to http://snoop.minecraft.net.
false - disable snooping.
true - enable snooping.
*/
private bool _snooperEnabled = true;
/*
Server checks connecting players against minecraft's account database. Only set this to false if your server is not connected to the Internet. Hackers with fake accounts can connect if this is set to false! If minecraft.net is down or inaccessible, no players will be able to connect if this is set to true. Setting this variable to off purposely is called "cracking" a server, and servers that are presently with online mode off are called "cracked" servers, allowing players with unlicensed copies of Minecraft to join.
true - Enabled. The server will assume it has an Internet connection and check every connecting player.
false - Disabled. The server will not attempt to check connecting players.
*/
private bool _onlineMode = true;
/*
Enable PvP on the server. Players shooting themselves with arrows will only receive damage if PvP is enabled.
true - Players will be able to kill each other.
false - Players cannot kill other players (also known as Player versus Environment (PvE)).
Note: Indirect damage sources spawned by players (such as lava, fire, TNT and to some extent water, sand and gravel) will still deal damage to other players.
*/
private bool _pvp = true;
/*
Defines the difficulty (such as damage dealt by mobs and the way hunger and poison affects players) of the server.
0 - Peaceful
1 - Easy
2 - Normal
3 - Hard
*/
private int _difficulty = 1;
/*
Defines the mode of gameplay.
0 - Survival
1 - Creative
2 - Adventure
3 - Spectator
*/
private int _gamemode = 0;
/*
If non-zero, players are kicked from the server if they are idle for more than that many minutes.
Note: Idle time is reset when the server receives one of the following packets:
102 (0x66) WindowClick
108 (0x6c) ButtonClick
130 (0x82) UpdateSign
14 (0xe) BlockDig
15 (0xf) Place
16 (0x10) BlockItemSwitch
18 (0x12) ArmAnimation
19 (0x13) EntityAction
205 (0xcd) ClientCommand
3 (0x3) Chat
7 (0x7) UseEntity
*/
private int _playerIdleTimeout = 0;
/*
The max numbers of players that can play on the server at the same time. Note that if more players are on the server it will use more resources. Note also, admin connections are not counted against the max players.
*/
private int _maxPlayers = 20;
/*
Determines if monsters will be spawned.
true - Enabled. Monsters will appear at night and in the dark.
false - Disabled. No monsters.
This does nothing if difficulty = 0 (peaceful) Unless your difficulty is not set to 0, when a monster can still spawn from a Monster Spawner. Tip: if you have major lag, turn this off/set to false.
*/
private bool _spawnMonsters = true;
/*
Defines whether structures (such as villages) will be generated.
false - Structures will not be generated in new chunks.
true - Structures will be generated in new chunks.
Note: Dungeons will still generate if this is set to false.
*/
private bool _generateStructures = true;
/*
Sets the amount of world data the server sends the client, measured in chunks in each direction of the player (radius, not diameter). It determines the server-side viewing distance. (see Render distance)
10 is the default/recommended. If you have major lag, reduce this value.
*/
private int _viewDistance = 10;
/*
MOTD is short for Message of the day, though you do not need to change it every day. The MOTD is displayed when people join the server.
*/
private string _motd = "A Tekkit Server";
public string GeneratorSettings
{
get { return _generatorSettings; }
set { _generatorSettings = value; }
}
public int OpPermissionLevel
{
get { return _opPermissionLevel; }
set { _opPermissionLevel = value; }
}
public string AllowNether
{
get { return _allowNether ? "true" : "false"; }
set { _allowNether = value == "true" ? true : false; }
}
public string LevelName
{
get { return _levelName; }
set { _levelName = value; }
}
public string EnableQuery
{
get { return _enableQuery ? "true" : "false"; }
set { _enableQuery = value == "true" ? true : false; }
}
public string AllowFlight
{
get { return _allowFlight ? "true" : "false"; }
set { _allowFlight = value == "true" ? true : false; }
}
public int ServerPort
{
get { return _serverPort; }
set { _serverPort = value; }
}
public string LevelType
{
get { return _levelType; }
set { _levelType = value; }
}
public string EnableRcon
{
get { return _enableRcon ? "true" : "false"; }
set { _enableRcon = value == "true" ? true : false; }
}
public string ForceGameMode
{
get { return _forceGameMode ? "true" : "false"; }
set { _forceGameMode = value == "true" ? true : false; }
}
public string LevelSeed
{
get { return _levelSeed; }
set { _levelSeed = value; }
}
public string ServerIp
{
get { return _serverIp; }
set { _serverIp = value; }
}
public int MaxBuildHeight
{
get { return _maxBuildHeight; }
set { _maxBuildHeight = value; }
}
public string SpawnNpcs
{
get { return _spawnNpcs ? "true" : "false"; }
set { _spawnNpcs = value == "true" ? true : false; }
}
public string WhiteList
{
get { return _whiteList ? "true" : "false"; }
set { _whiteList = value == "true" ? true : false; }
}
public string SpawnAnimals
{
get { return _spawnAnimals ? "true" : "false"; }
set { _spawnAnimals = value == "true" ? true : false; }
}
public string TexturePack
{
get { return _texturePack; }
set { _texturePack = value; }
}
public string HardCode
{
get { return _hardcore ? "true" : "false"; }
set { _hardcore = value == "true" ? true : false; }
}
public string SnooperEnabled
{
get { return _snooperEnabled ? "true" : "false"; }
set { _snooperEnabled = value == "true" ? true : false; }
}
public string OnlineMode
{
get { return _onlineMode ? "true" : "false"; }
set { _onlineMode = value == "true" ? true : false; }
}
public string PVP
{
get { return _pvp ? "true" : "false"; }
set { _pvp = value == "true" ? true : false; }
}
public int Difficulty
{
get { return _difficulty; }
set { _difficulty = value; }
}
public int GameMode
{
get { return _gamemode; }
set { _gamemode = value; }
}
public int PlayerIdleTimeout
{
get { return _playerIdleTimeout; }
set { _playerIdleTimeout = value; }
}
public int MaxPlayers
{
get { return _maxPlayers; }
set { _maxPlayers = value; }
}
public string SpawnMonsters
{
get { return _spawnMonsters ? "true" : "false"; }
set { _spawnMonsters = value == "true" ? true : false; }
}
public string GenerateStructures
{
get { return _generateStructures ? "true" : "false"; }
set { _generateStructures = value == "true" ? true : false; }
}
public int ViewDistance
{
get { return _viewDistance; }
set { _viewDistance = value; }
}
public string Motd
{
get { return _motd; }
set { _motd = value; }
}
Below is the method that eventually should read the file, check it line by line if it contains one of the strings from the tekkitSettingsKeys, update the TekkitServerSettings object's appropriate setter and return the TekkitServerSettings object
public static TekkitServerSettings Load(string settingsFilePath)
{
TekkitServerSettings serverSettingsToLoad = new TekkitServerSettings();
string[] linesFromSettingsFile = File.ReadAllLines(settingsFilePath);
foreach (string tekkitSettingsKey in tekkitSettingsKeys)
{
foreach (string lineFromSettingsFile in linesFromSettingsFile)
{
if (lineFromSettingsFile.Contains(tekkitSettingsKey))
{
// Remove the key from the line
var settingValue = lineFromSettingsFile.Replace(tekkitSettingsKey,"");
// update serverSettingsToLoad's value with the appropriate value in an elegant manner.
??
}
}
}
// Check that everything is good
// return the object
}
I have to somehow know the setter i have to update, and i believe there is a somewhat more elegant way to accomplish this rather than make a bunch of if/else statements or a huge switch?
Example
When it runs the second foreach it reads that the string level-type=DEFAULT contains level-type=. It removes level-type= and ends up with settingValue = "DEFAULT".
I now have the value and i know that the key is level-type=. Somehow i want to accomplish serverSettingsToLoad.LevelType = "DEFAULT" and so forth.
Any suggestions on how to accomplish what i want in the best way? Maybe the way i have set this up to start with isnt the best way?
Thanks!
A simple dictionary will do:
class TekkitServerSettings
{
private readonly static Dictionary<string, Action<TekkitServerSettings, string>>
_settingSetters =
new Dictionary<string, Action<TekkitServerSettings, string>>()
{
{ "generator-settings=", (s, v) => s.GeneratorSettings = v },
{ "op-permission-level=", (s, v) => s.OpPermissionLevel = int.Parse(v) }
};
public string GeneratorSettings { get; set; }
public int OpPermissionLevel { get; set; }
}
This allows you to load the settings simply by finding the appropriate setter action. Of course, you'll probably want some helper methods (something to handle errors the way you want, for example).
The usage is as simple as
if (_settingSetters.ContainsKey(tekkitSettingsKey))
{
_settingSetters[tekkitSettingsKey](serverSettingsToLoad, settingValue);
}
There's plenty of tweaks you'll want to do, of course. For example, you might make the dictionary case-insensitive, or you might want to add some error handling that will tell the user what's broken in his config file (for example, "'5' is an invalid value for op-permissions-level" or "'4x' is an invalid value for op-permissions-level").
Note that I assume you're reading the config file line-by-line, setting any known settings as you go. There's little point in going through the file again and again just to find one of the unordered lines. Just go line-by-line, and search for the setting in the dictionary - it's much faster, and much cleaner.
If you really want to use a class to do it (I'd personally use a dictionary like #Luaan's answer), then you're almost certainly going to need to use Reflection to achieve this.
Using reflection you can enumerate all the fields on the current class instance, find the one with the matching name and dynamically set the value. Here is a brief example modified from: https://msdn.microsoft.com/en-us/library/6z33zd7h.aspx
TekkitServerSettings settings = new TekkitServerSettings();
Type type = typeof(settings);
FieldInfo myField = type.GetField("_maxBuildHeight", BindingFlags.NonPublic | BindingFlags.Instance);
myField.SetValue(settings, 55);
The important class that you'll need to look into is the FieldInfo class.

Making elements changeable from references

So! I've got a C# array.
And I've got a function that returns an element from the array, so the data from that reference can be accessed. Yay!
It would be really super awesome convenient if changing that reference then affected that original element in the array. Is this what static variables do? Is there a way to do it? How to do? For example:
Function A finds an item:
public TutorialPopupBehavior GetBehavior(string behaviorName) {
foreach(TutorialPopupBehavior beh in _tutorialItems) {
if(beh._popupName == behaviorName) {
return beh;
}
}
print ("Could not find behavior of name " + behaviorName);
return null;
}
And then returns it to function B, which then, ideally, would be able to change a property of the returned item:
public void SetTutorialItem(bool state, string itemName) {
TutorialPopupBehavior beh = GetBehavior(itemName);
if(beh == null) {
print ("No tutorial item found, so can't set it to " + state);
return;
}
//idealistic code: beh._isShown = true;
}
The _isShown property of that element would then be changed permanently in the original _tutorialItems array...how do you all accomplish this, or design differently, so as to avoid the problem? The reason I ask is because I have a number of arrays to search, and I don't want to complicate my code by asking the same class to search through the same set of arrays more than once.
public void GetBehavior(string behaviorName, ref TutorialPopupBehavior b) {
foreach(TutorialPopupBehavior beh in _tutorialItems) {
if(beh._popupName == behaviorName) {
b = beh;
Return;
}
}
print ("Could not find behavior of name " + behaviorName);
b = null;
}
Read this msdn article

Custom workflow activity errors 'Value cannot be null'

I'm creating a custom workflow activity in VS2010 targeting .NET 3.5. The DLL is actually being used in a Microsoft System Center Service Manager custom workflow, but I don't think that is my issue.
I have a public string property, that the user types in the string of what the activity should use. However, when the WF runs, it errors out 'value cannot be null'. I want to target if it is my code or something else.
When we drag my custom activity onto the designer, I'm able to type in the text of the string on the designer for that property.
public static DependencyProperty ChangeRequestStageProperty = DependencyProperty.Register("ChangeRequestStage", typeof(String), typeof(UpdateChangeRequestStage));
[DescriptionAttribute("The value to set the ChangeRequestStage Property in the ChangeRequest Extension class.")]
[CategoryAttribute("Change Request Extension")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
public String Stage
{
get { return ((String)(base.GetValue(UpdateChangeRequestStage.ChangeRequestStageProperty))); }
set { base.SetValue(UpdateChangeRequestStage.ChangeRequestStageProperty, value); }
}
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
EnterpriseManagementGroup emg = CreateEMG();
//System.WorkItem.ChangeRequest Extension - ClassExtension_928bec0a_cac4_4a0a_bd89_7146c9052fbe
ManagementPackClass mpcChangeRequest = emg.EntityTypes.GetClass(new Guid("8c6c6057-56ad-3862-47ec-dc0dde80a071"));
//System.WorkItemContainsActivity Relationship Class
ManagementPackRelationship workItemContainsActivityRelationship = emg.EntityTypes.GetRelationshipClass(new Guid("2DA498BE-0485-B2B2-D520-6EBD1698E61B"));
EnterpriseManagementObject changeRequest = null;
//Loop thru each emo (Change Request in this case), and assign it. There will never be more than 1 emo returned
foreach (EnterpriseManagementObject obj in emg.EntityObjects.GetRelatedObjects<EnterpriseManagementObject>(executionContext.ContextGuid, workItemContainsActivityRelationship, TraversalDepth.OneLevel, ObjectQueryOptions.Default))
{ changeRequest = obj; }
EnterpriseManagementObjectProjection emop = new EnterpriseManagementObjectProjection(changeRequest);
if (emop != null)
{ emop.Object[mpcChangeRequest, "ChangeRequestStage"].Value = Stage; }
emop.Commit();
return base.Execute(executionContext);
}
Since it is getting a 'value cannot be null' error, I'm guessing it's on this line:
emop.Object[mpcChangeRequest, "ChangeRequestStage"].Value = Stage;
I'm going to test and see if hardcoding a value works or not. Any ideas?
enter code here
try this
if (emop != null && emop.Object[mpcChangeRequest, "ChangeRequestStage"] != null)
emop.Object[mpcChangeRequest, "ChangeRequestStage"].Value = Stage
I didn't want to leave this question wide open, so I'm updating it as to how I resolved this (a long time ago).
Rather than working with an EnterpriseManagementObjectProjection (emop), I worked with a standard EnterpriseManagementObject (emo). From there, I was able to follow a similar format from above:
ManagementPackClass mpcChangeRequest = emg.EntityTypes.GetClass(new Guid("8c246fc5-4e5e-0605-dc23-91f7a362615b"));
changeRequest[mpcChangeRequest, "ChangeRequestStage"].Value = this.Stage;
changeRequest.Commit();

Get-methods or private property?

This is just a matter of taste but I'd like to hear some of your opinions (that's also why this question is marked as subjective).
If I have a property, say
private string _Text;
public string Text;
get
{
object tmp = ViewState["Text"];
if (tmp != null)
_Text = Convert.ToString(tmp);
return _Text;
}
set
{
ViewState.Add("Text", value);
}
Now this is the property which may be specified by the programmer, by setting some custom text. This is then mapped - say - to some control on the UI. In the default case however, the Text of the control comes from a predefined resource file. So internally to handle that internally in a better way, I'd have some central point where I check whether the user has specified the "Text" property (above) and if so, use that data, otherwise rely on the default one from the resource file.
So what approach would you take? I have two options in mind:
private string ResolvedText
{
get
{
if(!string.IsNullOrEmpty(Text))
return Text;
else
//return the one from the resource file
}
}
Or put everything in a method
public string GetResolvedText()
{
if(!string.IsNullOrEmpty(Text))
return Text;
else
//return the one from the resource file
}
The question may sound stupid to you since it's really a minor difference. But I'd like to know whether there are some conventions about this.
Thx
Personally, I'd take the body of your GetResolvedText method, and use it in the property, thus:
private string _Text;
public string Text
{
get
{
if(string.IsNullOrEmpty(_Text))
//return the one from the resource file
else
return _Text;
}
set
{
_Text = value;
}
}
This puts all the responsibility for managing the string into the one place. The class itself can access _Text internally, if it needs the raw value.
I find that the best general rule here is: if calling the action twice results in multiple resource calls or different behaviour - use a method.
So, in your example use of a property is fine if it caches:
public string ResolvedText
{
get { return Text ?? (Text = GetResolvedText()); }
}
However the method doesn't need to - users expect it to be a more intensive operation:
public string GetResolvedText()
{
//return the one from the resource file
}
The design question is how do you want this class to be used?
A property will get called as if it is a 'cheap' operation:
if( myInstance.ResolvedText != null &&
myInstance.ResolvedText.Length > 5 )
Response.Write( myInstance.ResolvedText );
A method hints to the developer that they should call it as few times as possible:
string resolvedText = myInstance.GetResolvedText();
if( resolvedText != null &&
resolvedText.Length > 5 )
Response.Write( resolvedText );
Personally I prefer to keep interim classes simple, so in the vast majority of cases I would use the method model.
As this is a fairly standard convention you should avoid properties that don't cache and methods that do.
I would keep this as a property, since it represents a single value that does not require a lot of computing to retrieve.
To me, if the getter can't throw an exception, or null/invalid value, it should be a property. It is what properties are made for.
BUT, if you do some complicated stuff, if has to be a a function getter. Obviously here you have only 1 if, so I would use a property.
Reworking together your example and Steve's answer, plus adding in some caching, as obviously the resource value should be read only once since it never changes and by contract we must return the value from the property as fast as possible:
private static string ResourceText;
static [constructor]
{
ResourceText = //get resource;
}
private string text;
public string Text;
get
{
string tmp = (string)ViewState["Text"];
if (!String.IsNullOrEmpty(tmp))
text = tmp;
else
text = ResourceText;
return text;
}
set
{
ViewState.Add("Text", value);
// Note: passing null or empty strings will not work.
}

Categories

Resources