Getting assembly version info from static class throws a stackoverflow exception - c#

I have struggled with this for a bit, and I have a feeling I am very close. In a .NET MVC web application I have used to have assemblyinfo information displayed in the front end without issue. In a bit of optimization I wanted to move that code out to a general purpose helper class.
For ease of use I have made it a static class, but I have hit several snags in the process. But now it throws a System.StackOverflowException when I try to use it, sadly. Here is the code:
public static class VersionInformationHelper
{
public static string GetVersionNumber
{
get
{
if (!string.IsNullOrWhiteSpace(GetVersionNumber.GetType().Assembly.GetName().Version.ToString()))
{
return "v" + GetVersionNumber.GetType().Assembly.GetName().Version.ToString();
}
else
{
return string.Empty;
}
}
}
/// <remark>
/// This doesnt exactly return the commit hash so to speak. Well it does, but Teamcity is set to enter the corresponding commit hash information when building,
/// into productversion in "AssemblyInfo.cs". It could be any string really. But we assume that a commit hash will always be in that location.
/// It's "Assembly informational version" in the assemblyinfo patcher build feature in teamcity.
/// </remark>
public static string GetCommitHash
{
get
{
if (!string.IsNullOrWhiteSpace(System.Diagnostics.FileVersionInfo.GetVersionInfo(GetVersionNumber.GetType().Assembly.Location).ProductVersion))
{
return System.Diagnostics.FileVersionInfo.GetVersionInfo(GetVersionNumber.GetType().Assembly.Location).ProductVersion;
}
else
{
return string.Empty;
}
}
}
public static string GetBuildDate
{
get
{
return string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0:dd/MM/yy HH:mm:ss}", System.IO.File.GetLastWriteTime(GetVersionNumber.GetType().Assembly.Location));
}
}
}
EDIT
Fixed code based on feedback (GetVersionNumber and GetCommitHash" has been changed):
public static class VersionInformationHelper
{
public static string GetVersionNumber
{
get
{
if (!string.IsNullOrWhiteSpace(System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString()))
{
return "v" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
}
else
{
return string.Empty;
}
}
}
/// <remark>
/// This doesnt exactly return the commit hash so to speak. Well it does, but Teamcity is set to enter the corresponding commit hash information when building,
/// into productversion in "AssemblyInfo.cs". It could be any string really. But we assume that a commit hash will always be in that location.
/// It's "Assembly informational version" in the assemblyinfo patcher build feature in teamcity.
/// </remark>
public static string GetCommitHash
{
get
{
if (!string.IsNullOrWhiteSpace(System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).ProductVersion))
{
return System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).ProductVersion;
}
else
{
return string.Empty;
}
}
}
public static string GetBuildDate
{
get
{
return string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0:dd/MM/yy HH:mm:ss}", System.IO.File.GetLastWriteTime(GetVersionNumber.GetType().Assembly.Location));
}
}
}

You are reading GetVersionNumber from the getter of same GetVersionNumber (twice). This will loop infinitely (or until a stack overflow occurs).
You probably need to change the two occurences with Assembly.GetExecutingAssembly().GetName().Version.ToString() or another method to get the version.

Related

.NET inconsistent hash output

I have a class representing a unique real-world object, its name is personally identifiable information (a vehicle license plate if you're interested) so as a basic first step I am hashing the name and using that instead. (I know - salt required etc. - this is just a foundation)
I have a test which instantiates the object with a fixed input (a test name - "A") and asserts that the Id (Base 64 string of the hash output) is as expected. However, it occasionally fails(!!)
I dug a bit deeper and here's a screenshot of a conditional breakpoint which breaks only when the hash output isn't the norm. The input is still as expected (the 'bytes' variable contains { 65 }, but the output is different from the normal sha384 output hash (normally it's "rRSq8lAgvvL9Tj617AxQJyzf1mB0sO0DfJoRJUMhqsBymYU3S+6qW4ClBNBIvhhk")
Lines 19-25 are split up a bit to facilitate debugging, but otherwise this class is as it should be.
Any clues as to how this is possible would be very welcome. Running Windows 11, using .NET 7 and the latest version of Visual Studio Enterprise.
Here's a pic of a conditional breakpoint being hit where hash output is not the norm:
Here's the code should anyone wish to try to reproduce it (note it's not consistent: it's just occasional)
using System.Security.Cryptography;
using System.Text;
namespace Domain.Models.Object
{
/// <summary>
/// One-way identifier
/// </summary>
public record ObjectIdentifier
{
private static SHA384 hash = SHA384.Create();
public ObjectIdentifier(string name)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
var bytes = Encoding.UTF8.GetBytes(name);
Id = Convert.ToBase64String(hash.ComputeHash(bytes));
int x = 0;
x++;
}
public string Id { get; init; }
public override string ToString()
{
return Id;
}
}
}
And here's the test:
[Fact]
public void ObjectIdentifier_AsExpected()
{
// arrange
var obj = new ObjectIdentifier("A");
// assert
Assert.Equal("rRSq8lAgvvL9Tj617AxQJyzf1mB0sO0DfJoRJUMhqsBymYU3S+6qW4ClBNBIvhhk", obj.Id);
}
I also note that the new hash value is not consistently the same: here's another failure with a different output from the previous screenshot:
I also note that adding this to line 20 causes the inconsistency to stop happening altogether...
Unfortunately, this is not a suitable fix :P
Debug.Assert(bytes.Length == 1 && bytes[0] == 65)
Update
The invalid outputs appear to just be the two supplied above, I haven't observed any further variants.
Also, changing it to be a class (instead of a record) makes no difference.
I'm also observing this effect in a test console app which has only two identifiers supplied to it, but in fact more than two hashes are output:
So, as Matt kindly pointed out in the comments, this operation isn't thread-safe. The shared worker object (shared because it was static) was to blame. An easy one to miss - and a great example of why unit tests are a must!
I opted to use an object pool to get a unique worker per instantiation while allowing for some reduction in allocation overhead:
using Domain.Implementations;
using Microsoft.Extensions.ObjectPool;
using System.Text;
namespace Domain.Models.Object
{
/// <summary>
/// One-way identifier
/// </summary>
public class ObjectIdentifier
{
private static ObjectPool<HashWrapper> hashObjects = ObjectPool.Create<HashWrapper>();
public ObjectIdentifier(string name)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
var hashworker = hashObjects.Get();
try
{
Id = Convert.ToBase64String(hashworker.Value.ComputeHash(Encoding.UTF8.GetBytes(name)));
}
finally
{
hashObjects.Return(hashworker);
}
}
public string Id { get; init; }
public override string ToString()
{
return Id;
}
}
}
The hash wrapper class (wraps the worker and provides a public constructor for the object pool)
internal class HashWrapper
{
public HashWrapper()
{
Value = SHA384.Create();
}
public HashAlgorithm Value { get; private set; }
}
Update
This implementation with a shared pool provided a (very minor) increase in speed and memory allocation when constructing higher numbers of objects. For smaller numbers, there is a (very minor) performance penalty. YMMV - see below.
This benchmark ran a version with Shared = true (normal lock on a shared object), false (new sha worker instance for each instantiation) and null [? in the column] : to signal using an object pool

How to check if parameters are null when using positional record constructors and/or init properties?

I would like check no null parameters are assigned to record fields and let the properties have comments. I have found out the following arrangement does the trick for comments, but I lack ideas to check for null parameters without turning this record into a class.
So, a question: Is it possible to check during runtime that nulls won't be assigned to record fields? If so, how could one do it while still using records?
public record Test(string TestString)
{
/// <summary>
/// This is one way to get a comment on record properties. Are there others?
/// </summary>
public string TestString { get; init; } = TestString;
}
The code is also as a gist here.
This is an addition, but maybe helps with the accepted answer and the comment of different code.
It was because the code in the gist did a null check like
public record Test(string TestString)
{
/// <summary>
/// This is one way to get a comment on record properties. Are there others?
/// </summary>
public string TestString { get; init; } = TestString ?? throw new ArgumentNullException();
}
For a reason or another, I didn't include this pondering in the original question if there's maybe a shorter way. :)
<edit: The .NET 6 ArgumentNullException.ThrowIfNull(obj) could be handy here (or ThrowHelper).
You have to handle checks during inline assignment, as you've already discovered in your gist.
One possibility is to call an extension method to wrap any behavior.
public record Test(string TestString)
{
/// <summary>
/// This is one way to get a comment on record properties. Are there others?
/// </summary>
public string TestString { get; init; } = ValidationExtensions.Validate(TestString);
}
public static class ValidationExtensions
{
public static string Validate(string input)
{
if (string.IsNullOrEmpty(input))
throw new NullReferenceException();
return input;
}
}
This will correctly throw during initialization of the record:
var x = new Test(null);

c# convert string to table ( for easier using table, like command) [duplicate]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
When building console applications that take parameters, you can use the arguments passed to Main(string[] args).
In the past I've simply indexed/looped that array and done a few regular expressions to extract the values. However, when the commands get more complicated, the parsing can get pretty ugly.
So I'm interested in:
Libraries that you use
Patterns that you use
Assume the commands always adhere to common standards such as answered here.
I would strongly suggest using NDesk.Options (Documentation) and/or Mono.Options (same API, different namespace). An example from the documentation:
bool show_help = false;
List<string> names = new List<string> ();
int repeat = 1;
var p = new OptionSet () {
{ "n|name=", "the {NAME} of someone to greet.",
v => names.Add (v) },
{ "r|repeat=",
"the number of {TIMES} to repeat the greeting.\n" +
"this must be an integer.",
(int v) => repeat = v },
{ "v", "increase debug message verbosity",
v => { if (v != null) ++verbosity; } },
{ "h|help", "show this message and exit",
v => show_help = v != null },
};
List<string> extra;
try {
extra = p.Parse (args);
}
catch (OptionException e) {
Console.Write ("greet: ");
Console.WriteLine (e.Message);
Console.WriteLine ("Try `greet --help' for more information.");
return;
}
I really like the Command Line Parser Library ( http://commandline.codeplex.com/ ). It has a very simple and elegant way of setting up parameters via attributes:
class Options
{
[Option("i", "input", Required = true, HelpText = "Input file to read.")]
public string InputFile { get; set; }
[Option(null, "length", HelpText = "The maximum number of bytes to process.")]
public int MaximumLenght { get; set; }
[Option("v", null, HelpText = "Print details during execution.")]
public bool Verbose { get; set; }
[HelpOption(HelpText = "Display this help screen.")]
public string GetUsage()
{
var usage = new StringBuilder();
usage.AppendLine("Quickstart Application 1.0");
usage.AppendLine("Read user manual for usage instructions...");
return usage.ToString();
}
}
The WPF TestApi library comes with one of the nicest command line parsers for C# development. I highly recommend looking into it, from Ivo Manolov's blog on the API:
// EXAMPLE #2:
// Sample for parsing the following command-line:
// Test.exe /verbose /runId=10
// This sample declares a class in which the strongly-
// typed arguments are populated
public class CommandLineArguments
{
bool? Verbose { get; set; }
int? RunId { get; set; }
}
CommandLineArguments a = new CommandLineArguments();
CommandLineParser.ParseArguments(args, a);
Look at http://github.com/mono/mono/tree/master/mcs/class/Mono.Options/
Looks like everybody has their own pet command-line parsers, figure I had better add mine as well :).
http://bizark.codeplex.com/
This library contains a command-line parser that will initialize a class with the values from the command-line. It has a ton of features (I've been building it up over many years).
From the documentation...
Command-line parsing in the BizArk framework has these key features:
Automatic initialization: Class properties are automatically set based on the command-line arguments.
Default properties: Send in a value without specifying the property name.
Value conversion: Uses the powerful ConvertEx class also included in BizArk to convert values to the proper type.
Boolean flags: Flags can be specified by simply using the argument (ex, /b for true and /b- for false) or by adding the value true/false, yes/no, etc.
Argument arrays: Simply add multiple values after the command-line name to set a property that is defined as an array. Ex, /x 1 2 3 will populate x with the array { 1, 2, 3 } (assuming x is defined as an array of integers).
Command-line aliases: A property can support multiple command-line aliases for it. For example, Help uses the alias ?.
Partial name recognition: You don’t need to spell out the full name or alias, just spell enough for the parser to disambiguate the property/alias from the others.
Supports ClickOnce: Can initialize properties even when they are specified as the query string in a URL for ClickOnce deployed applications. The command-line initialization method will detect if it is running as ClickOnce or not so your code doesn’t need to change when using it.
Automatically creates /? help: This includes nice formatting that takes into account the width of the console.
Load/Save command-line arguments to a file: This is especially useful if you have multiple large, complex sets of command-line arguments that you want to run multiple times.
I wrote a C# command line argument parser a while back. Its at: http://www.codeplex.com/CommandLineArguments
CLAP (command line argument parser) has a usable API and is wonderfully documented. You make a method, annotating the parameters. https://github.com/adrianaisemberg/CLAP
There are numerous solutions to this problem. For completeness and to provide the alternative if someone desires I'm adding this answer for two useful classes in my google code library.
The first is ArgumentList which is responsible only for parsing command line parameters. It collects name-value pairs defined by switches '/x:y' or '-x=y' and also collects a list of 'unnamed' entries. It's basic usage is discussed here, view the class here.
The second part of this is the CommandInterpreter which creates a fully-functional command-line application out of your .Net class. As an example:
using CSharpTest.Net.Commands;
static class Program
{
static void Main(string[] args)
{
new CommandInterpreter(new Commands()).Run(args);
}
//example ‘Commands’ class:
class Commands
{
public int SomeValue { get; set; }
public void DoSomething(string svalue, int ivalue)
{ ... }
With the above example code you can run the following:
Program.exe DoSomething "string value" 5
-- or --
Program.exe dosomething /ivalue=5 -svalue:"string value"
It's as simple as that or as complex as you need it to be. You can review the source code, view the help, or download the binary.
I like that one, because you can "define rules" for the arguments, needed or not,...
or if you're a Unix guy, than you might like the GNU Getopt .NET port.
You may like my one Rug.Cmd
Easy to use and expandable command line argument parser. Handles: Bool, Plus / Minus, String, String List, CSV, Enumeration.
Built in '/?' help mode.
Built in '/??' and '/?D' document generator modes.
static void Main(string[] args)
{
// create the argument parser
ArgumentParser parser = new ArgumentParser("ArgumentExample", "Example of argument parsing");
// create the argument for a string
StringArgument StringArg = new StringArgument("String", "Example string argument", "This argument demonstrates string arguments");
// add the argument to the parser
parser.Add("/", "String", StringArg);
// parse arguemnts
parser.Parse(args);
// did the parser detect a /? argument
if (parser.HelpMode == false)
{
// was the string argument defined
if (StringArg.Defined == true)
{
// write its value
RC.WriteLine("String argument was defined");
RC.WriteLine(StringArg.Value);
}
}
}
Edit: This is my project and as such this answer should not be seen as an endorsement from a third party. That said I do use it for every command line based program I write, it is open source and it is my hope that others may benefit from it.
There is a command line argument parser at http://www.codeplex.com/commonlibrarynet
It can parse arguments using
1. attributes
2. explicit calls
3. single line of multiple arguments OR string array
It can handle things like the following:
-config:Qa -startdate:${today} -region:'New York' Settings01
It's very easy to use.
This is a handler I wrote based on the Novell Options class.
This one is aimed at console applications that execute a while (input !="exit") style loop, an interactive console such as an FTP console for example.
Example usage:
static void Main(string[] args)
{
// Setup
CommandHandler handler = new CommandHandler();
CommandOptions options = new CommandOptions();
// Add some commands. Use the v syntax for passing arguments
options.Add("show", handler.Show)
.Add("connect", v => handler.Connect(v))
.Add("dir", handler.Dir);
// Read lines
System.Console.Write(">");
string input = System.Console.ReadLine();
while (input != "quit" && input != "exit")
{
if (input == "cls" || input == "clear")
{
System.Console.Clear();
}
else
{
if (!string.IsNullOrEmpty(input))
{
if (options.Parse(input))
{
System.Console.WriteLine(handler.OutputMessage);
}
else
{
System.Console.WriteLine("I didn't understand that command");
}
}
}
System.Console.Write(">");
input = System.Console.ReadLine();
}
}
And the source:
/// <summary>
/// A class for parsing commands inside a tool. Based on Novell Options class (http://www.ndesk.org/Options).
/// </summary>
public class CommandOptions
{
private Dictionary<string, Action<string[]>> _actions;
private Dictionary<string, Action> _actionsNoParams;
/// <summary>
/// Initializes a new instance of the <see cref="CommandOptions"/> class.
/// </summary>
public CommandOptions()
{
_actions = new Dictionary<string, Action<string[]>>();
_actionsNoParams = new Dictionary<string, Action>();
}
/// <summary>
/// Adds a command option and an action to perform when the command is found.
/// </summary>
/// <param name="name">The name of the command.</param>
/// <param name="action">An action delegate</param>
/// <returns>The current CommandOptions instance.</returns>
public CommandOptions Add(string name, Action action)
{
_actionsNoParams.Add(name, action);
return this;
}
/// <summary>
/// Adds a command option and an action (with parameter) to perform when the command is found.
/// </summary>
/// <param name="name">The name of the command.</param>
/// <param name="action">An action delegate that has one parameter - string[] args.</param>
/// <returns>The current CommandOptions instance.</returns>
public CommandOptions Add(string name, Action<string[]> action)
{
_actions.Add(name, action);
return this;
}
/// <summary>
/// Parses the text command and calls any actions associated with the command.
/// </summary>
/// <param name="command">The text command, e.g "show databases"</param>
public bool Parse(string command)
{
if (command.IndexOf(" ") == -1)
{
// No params
foreach (string key in _actionsNoParams.Keys)
{
if (command == key)
{
_actionsNoParams[key].Invoke();
return true;
}
}
}
else
{
// Params
foreach (string key in _actions.Keys)
{
if (command.StartsWith(key) && command.Length > key.Length)
{
string options = command.Substring(key.Length);
options = options.Trim();
string[] parts = options.Split(' ');
_actions[key].Invoke(parts);
return true;
}
}
}
return false;
}
}
My personal favorite is http://www.codeproject.com/KB/recipes/plossum_commandline.aspx by Peter Palotas:
[CommandLineManager(ApplicationName="Hello World",
Copyright="Copyright (c) Peter Palotas")]
class Options
{
[CommandLineOption(Description="Displays this help text")]
public bool Help = false;
[CommandLineOption(Description = "Specifies the input file", MinOccurs=1)]
public string Name
{
get { return mName; }
set
{
if (String.IsNullOrEmpty(value))
throw new InvalidOptionValueException(
"The name must not be empty", false);
mName = value;
}
}
private string mName;
}
I recently came across The FubuCore Command line parsing implementation I really like it, the reasons being:
it's easy to use - although I couldn't find a documentation for it, the FubuCore solution also provides a project containing a nice set of Unit Tests that speak more about the functionality than any documentation could
it has a nice object oriented design, no code repetition or other such things that I used to have in my command line parsing apps
it's declarative: you basically write classes for the Commands and sets of parameters and decorate them with attributes to set various options (e.g. name, description, mandatory/optional)
the library even prints a nice Usage Graph, based on these definitions
Below is a simple example on how to use this. To illustrate the usage, I've written a simple utility that has two commands:
- add (adds an object to a list - an object consists of a name(string), value(int) and a boolean flag)
- list (lists all the currently added objects)
First of all, I wrote a Command class for the 'add' command:
[Usage("add", "Adds an object to the list")]
[CommandDescription("Add object", Name = "add")]
public class AddCommand : FubuCommand<CommandInput>
{
public override bool Execute(CommandInput input)
{
State.Objects.Add(input); // add the new object to an in-memory collection
return true;
}
}
This command takes a CommandInput instance as parameter, so I define that next:
public class CommandInput
{
[RequiredUsage("add"), Description("The name of the object to add")]
public string ObjectName { get; set; }
[ValidUsage("add")]
[Description("The value of the object to add")]
public int ObjectValue { get; set; }
[Description("Multiply the value by -1")]
[ValidUsage("add")]
[FlagAlias("nv")]
public bool NegateValueFlag { get; set; }
}
The next command is 'list', which is implemented as follows:
[Usage("list", "List the objects we have so far")]
[CommandDescription("List objects", Name = "list")]
public class ListCommand : FubuCommand<NullInput>
{
public override bool Execute(NullInput input)
{
State.Objects.ForEach(Console.WriteLine);
return false;
}
}
The 'list' command takes no parameters, so I defined a NullInput class for this:
public class NullInput { }
All that's left now is to wire this up in the Main() method, like this:
static void Main(string[] args)
{
var factory = new CommandFactory();
factory.RegisterCommands(typeof(Program).Assembly);
var executor = new CommandExecutor(factory);
executor.Execute(args);
}
The program works as expected, printing hints about the correct usage in case any commands are invalid:
------------------------
Available commands:
------------------------
add -> Add object
list -> List objects
------------------------
And a sample usage for the 'add' command:
Usages for 'add' (Add object)
add <objectname> [-nv]
-------------------------------------------------
Arguments
-------------------------------------------------
objectname -> The name of the object to add
objectvalue -> The value of the object to add
-------------------------------------------------
-------------------------------------
Flags
-------------------------------------
[-nv] -> Multiply the value by -1
-------------------------------------
Powershell Commandlets.
Parsing done by powershell based on attributes specified on the commandlets, support for validations, parameter sets, pipelining, error reporting, help, and best of all returning .NET objects for use in other commandlets.
A couple links i found helpful getting started:
Quickstart Tutorial
Programming Guide on MSDN
Namespace Reference on MSDN
C# CLI is a very simple command-line argument parsing library that I wrote. It's well-documented and open source.
Genghis Command Line Parser may be a little out of date, but it is very feature complete and works pretty well for me.
I would suggest the open-source library CSharpOptParse. It parses the command line and hydrates a user-defined .NET object with the command-line input. I always turn to this library when writing a C# console application.
Please use the .net port of the apache commons cli API. This works great.
http://sourceforge.net/projects/dotnetcli/
and the original API for concepts and introduction
http://commons.apache.org/cli/
A very simple easy to use ad hoc class for command line parsing, that supports default arguments.
class CommandLineArgs
{
public static CommandLineArgs I
{
get
{
return m_instance;
}
}
public string argAsString( string argName )
{
if (m_args.ContainsKey(argName)) {
return m_args[argName];
}
else return "";
}
public long argAsLong(string argName)
{
if (m_args.ContainsKey(argName))
{
return Convert.ToInt64(m_args[argName]);
}
else return 0;
}
public double argAsDouble(string argName)
{
if (m_args.ContainsKey(argName))
{
return Convert.ToDouble(m_args[argName]);
}
else return 0;
}
public void parseArgs(string[] args, string defaultArgs )
{
m_args = new Dictionary<string, string>();
parseDefaults(defaultArgs );
foreach (string arg in args)
{
string[] words = arg.Split('=');
m_args[words[0]] = words[1];
}
}
private void parseDefaults(string defaultArgs )
{
if ( defaultArgs == "" ) return;
string[] args = defaultArgs.Split(';');
foreach (string arg in args)
{
string[] words = arg.Split('=');
m_args[words[0]] = words[1];
}
}
private Dictionary<string, string> m_args = null;
static readonly CommandLineArgs m_instance = new CommandLineArgs();
}
class Program
{
static void Main(string[] args)
{
CommandLineArgs.I.parseArgs(args, "myStringArg=defaultVal;someLong=12");
Console.WriteLine("Arg myStringArg : '{0}' ", CommandLineArgs.I.argAsString("myStringArg"));
Console.WriteLine("Arg someLong : '{0}' ", CommandLineArgs.I.argAsLong("someLong"));
}
}

c# how to use Property

I want to learn more about c#, and I've heard that you should use Private specifier and use get/set to make it public.
I got a small application that take textbox data and writes it to a file. And it encrypts the file.
But I can't graps the concept about getters and setters. Here is my one of my classes and Methods that writes to a file.
class MyClass
{
public static bool WriteToFile(string text)
{
string FileName = "C:\\crypt\\crypt.txt";
try
{
using (System.IO.StreamWriter WriteToFile = new System.IO.StreamWriter(FileName))
{
WriteToFile.Write(text);
WriteToFile.Close();
}
return true;
}
catch
{
return false;
}
}
But instead i want to use a property. How should i do it?
This is how i pass in the textbox-data from my main class.
public void button1_Click(object sender, EventArgs e)
{
MyClass c = new MyClass();
if (MyClass.WriteToFile(textBox1.Text))
MessageBox.Show("success, managed to write to the file");
else
MessageBox.Show("Error, Could not write to file. Please check....");
I've looked at various tutorials such as https://channel9.msdn.com/series/C-Fundamentals-for-Absolute-Beginners/15 and tutorials, but I really stuggling.
WriteToFile is a method.
Methods are methods, and properties are properties.
Methods encapsulate behaviour, while properties encapsulate state.
WriteToFile should not be a property, because it does not encapsulate state. In fact, it attempts to write into the file system.
An example of a property would be:
public class MyClass
{
private bool _canWrite;
/// Checks whether the file can be written into the file system
public bool CanWrite
{
get { return _canWrite; }
}
}
From another class, you would call it like this:
if(myClass.CanWrite)
{
// ...
}
Notice that CanWrite does not define any behaviour, it just defines a getter for the _canWrite field, this ensures that external classes don't get to see too much about your class.
Also notice that I define a getter only, this prevents others from setting your property.
There is not much to change to your design besides one little thing. But first things first:
Could you place that code into a property? Sure. Should you? Not at all. Your method WriteToFile is actually doing sth. and thats what methods are for. Properties on the other hand are used for modifying/storing data.
Thats why property-names sound more like Names while method-names generally sound like Commands:
Example
public class Sample
{
private string someText;
// This Property Stores or modifies SomeText
public string SomeText
{
get { return this.someText; }
set { this.someText = value; }
}
// Method that does sth. (writes sometext to a given File)
public void WriteSomeTextToFile(string File)
{
// ...
}
}
Why properties/modifiers?
it is considered good pratice to encapsulate data within propeties like in the example above. A small improvement could be the use of an AutoProperty like so:
public string SomeText { get; set; }
which basically results in the same structure as the combination of an encapsulated field like in the first example.
Why?: because this makes it easy to switch it out or to add logic to your get/set-operations.
For example, you could add validation:
public string SomeText
{
// ...
set
{
if (value.Length > 100)
throw new Exception("The given text is to long!");
this.someText = value;
}
}
SideNote: Possible improvement to your class
The only improvement I could think of is not to swallow the exception in your write method:
public void WriteToFile()
{
using (var fileWriter= new System.IO.StreamWriter(FileName))
{
fileWriter.Write(_text);
fileWriter.Close();
}
}
This is much cleaner and you would not have to "decision" cascades handling the same issue (your try/catch and if/else) are practically doing the same.
public void button1_Click(object sender, EventArgs e)
{
try
{
var c = new MyClass();
c.WriteToFile(textBox1.Text))
MessageBox.Show("success, managed to write to the file");
}
catch(Exception e)
{
MessageBox.Show("Error, Could not write to file. " + e.Message);
}
}
This way, you do not only have the same behaviour, but you also have more information than just the raw fact that your operation was unsuccessful (false)
Okay so I think for you case you don't need a property, but if we assume you wan't to create some kind of wrapper class that handles all your writing to files you could do something along the lines of
class AwesomeFileWriter
{
private const string FileName = "C:\\crypt\\crypt.txt";
private readonly string _text;
public AwesomeFileWriter(string text)
{
_text = text;
}
public bool WriteToFile()
{
try
{
using (System.IO.StreamWriter WriteToFile = new System.IO.StreamWriter(FileName))
{
WriteToFile.Write(_text);
WriteToFile.Close();
}
return true;
}
catch
{
return false;
}
}
}
Without actually showing you the code I'll try and explain getters and setters so you can understand their concept.
A property looks like a method to the internal class and field to an external class.
E.g. You are able to perform logic in your property whereas when you call the property from a different class it behaves just like any other field.
GET: Used to retrieve and return a property. You are able to perform some complex logic before actually returning your property. You are able to safely expose private variables via the Get without compromising on writing.
SET: Used to set the value of a property that may be private, constant or public. You are able to have control over the setting of the variable.
Usually properties are used to keep values as attributes; characteristics; settings.
Methods and functions you would think as actions.
e.g as shown below:
public class MyClass{
/// <summary>
/// Keeps the file name
/// </summary>
public string FileName { get; set; }
/// <summary>
/// Action to write the file
/// </summary>
/// <returns>Returns true if the info. was wrote into the file.</returns>
public bool WriteToFileSucceed()
{
try
{
using (System.IO.StreamWriter WriteToFile = new System.IO.StreamWriter(FileName))
{
WriteToFile.Write(text);
WriteToFile.Close();
}
return true;
}
catch
{
return false;
}
}}
...
public void button1_Click(object sender, EventArgs e){
MyClass myClass = new MyClass();
myClass.FileName = #"C:\crypt\crypt.txt";
if(myClass.WriteToFileSucceed())
{
MessageBox.Show("Success, managed to write to the file");
}
else
{
MessageBox.Show("Ops! Unable to write to the file.");
}}

Static code analysis on mandatory variable evaluation

I have this C# solution in which we use a certain pattern. A function returns true/false whether it succeed, and some value. If the function returned false, the value may not be used. Thus in the scope where such a function (with this particular pattern) is called, the IsSuccessful boolean must be evaluated.
We work with VS2013 + ReSharper 9. Is there a way to automatically check whether this pattern is obeyed in the code? If it is not possible with these tools, are there other tools? My last resort would be to write a unit test that performs this static code analysis.
Code example:
public ReturnValue<T> MyMethod()
{
try
{
....
return new ReturnValue<T>(someValue);
}
catch(Exception ex)
{
return new ReturnValue<T>(ex);
}
}
var returnValue = MyMethod();
if(!returnValue.IsSuccesful)
{
//Log error
return; //Can't go on, previous function failed
}
//Is successful continue code
public class ReturnValue<T>
{
public bool IsSuccessful { get; private set; }
public T Value { get; private set; }
public ReturnValue<T>(Exception ex)
{
IsSuccessful = false;
}
public ReturnValue<T>(T valueToReturn)
{
IsSuccessful = true;
Value = valueToReturn;
}
}
Edit:
I semi-solved my issue. Upon creation of the object the current stacktrace is saved (new StackTrace()). Upon destruction of the object (when the garbage collectors cleans it up), it is checked whether the IsSuccesful property of the object was ever evaluated during its lifespan. If not, a warning with the stacktrace is logged.

Categories