Changing a value before calling another constructor - c#

I have been trying to create some "cascading" constructors. One calls the other with more information that before. The two I have so far look like this.
public scan() : this(Environment.Local) { }
public scan(Environment env) {
//it then does some stuff constructor-y things
}
I would like to make another one that can call my second constructor by accepting a string that it will then convert into an Environment. Something to this effect:
public scan(string environment) : this(environment.toString()}
but it just doesn't seem to want to work how I am hoping. Is there a way to pass in this string then call my other environment accepting constructor?
Also the change i'm hoping to make is going to more substantial than just a toString() but I used that to illistrate the point.

I would do it this way: Create a static method that handles converting from string to enum. In this static method, check for validity and return local if not.
public class scan
{
public scan(Environment value) { }
public scan() : this(Environment.Local) { }
public scan(string s) : this(ParseEnum(s)) { }
private static Environment ParseEnum(string s)
{
// default to local
Environment value = Environment.Local;
// try parsing the string
Enum.TryParse<Environment>(s, out value);
// if sucessful, the new value will be returned
// if not, Environment.Local will be returned
return value;
}
public enum Environment
{
Local,
NotLocal,
AnotherOne
}
}

ToString won't work because you end up calling the constructor recursively (plus calling ToString on a string doesn't make much sense). It sounds like you want to Parse te string to an Environment value:
public scan(string environment) :
this((Environment)Enum.Parse(typeof(Environment),environment))
{
}
But you run the risk of an exception being thrown due to an invalid string value, which cannot be caught at compile time.

If Environment was a struct or a class, then you could override the casting operator and rewrite your contructor like this:
public scan(string environment) : this((Environment)environment)
It is not allowed to overload operators on Enum types, so you're out of luck here.

No. You cant call constructor inside of other constructor or do something with parameter inside your constructor that is passed to other constructor before other ctor is called. Yes you can call other constructor and pass result of method execution like ctor() : this(MyMethod()) but still it is not the same as calling other constructor from inside of your ctor.
Typically what is used is :
public scan() { // general initialization logic }
public scan(Environment env) : this()
{
//some special logic here that uses parameter env
}
Or something like windows forms InitializeComponent method. Initialization method that contains initialization logic.

Related

C# - When i try to create constructor, i get CS7036 error

Firstly, sorry for my English. I hope i can explain my problem.
I have class like this
public class CarCommandExecutorBase
{
protected readonly ICarCommand CarCommand;
public CarCommandExecutorBase(ICarCommand carCommand)
{
CarCommand = carCommand;
}
}
Also i have class like this
public class CarStringCommandExecutor : CarCommandExecutorBase, IStringCommand
{
public CarStringCommandExecutor(Car car)
{
// this Constructor gives me an error.
}
public void ExecuteCommand(string commandObject)
{
}
}
Error message:
[![error][1]][1]
What's the reason and how can i fix it? Thanks.
Since the only constructor in CarCommandExecutorBase is defined like this
public CarCommandExecutorBase(ICarCommand carCommand)
{
CarCommand = carCommand;
}
you have to pass an ICarCommand when creating an instance of CarCommandExecutorBase.
You have to provide an ICarCommand through the constructor of CarStringCommandExecutor, because when instantiating a derived type the base constructor(s) also get called.
See this answer for more detailed information about this: https://stackoverflow.com/a/1882778/8450550
You could do something like this to solve this error:
public class CarStringCommandExecutor : CarCommandExecutorBase, IStringCommand
{
...
public CarStringCommandExecutor(Car car, ICarCommand carCommand)
: base(carCommand) // base() points to the constructor of the base class
{
...
}
or maybe this
public class CarStringCommandExecutor : CarCommandExecutorBase, IStringCommand
{
...
public CarStringCommandExecutor(Car car)
: base(null) // passing null but be aware of NullReferenceExceptions
{
...
}
or you add another constructor to CarCommandExecutorBase which expects no arguments:
public class CarCommandExecutorBase
{
protected readonly ICarCommand CarCommand;
public CarCommandExecutorBase(ICarCommand carCommand)
{
CarCommand = carCommand;
}
// mark this constructor as protected, so only deriving types can call it
protected CarCommandExecutorBase()
{
}
}
Which solution works best in your case is up to you.
One of the things that isn't immediately apparent, thanks to "compiler magic", about a C# class is that every class has a constructor
It needs to be this way because it's a rule that object construction happens in a tree; you construct some class Z which inherits from Y which inherits from X which inherits from object, and Z's cosntructor invokes Y's invokes X's invokes object's, then they finish, in order of object, X, Y, Z and you have your nicely constructed thing - every constructor on the way up the tree had its chance to do its init and ready the object for use (the part of it that each constructor was responsible for)
Even classes that don't seem to have constructors, have constructors:
class X {
}
If you don't provide a constructor, C# provides one for you. You never see it in your source code; just imagine that in between reading the file and compiling it, the compiler inserts it for you. It takes no parameters, has no code, and does nothing other than call its base:
class X {
X():base() { } //C# invisibly writes this for you
}
If you provide a constructor but don't write the base... bit, C# puts base() in for you behind the scenes (and it always calls the no-argument base()) but critically it doesn't provide an empty constructor if you provided one already
This means if you have a class like:
class X{
X(string message){
...
}
}
Your class X has a constructor, so C# won't provide the empty one, so now anything that tries to construct your class must provide a string message:
X x = new X("hello");
If you now inherit from X, you might do one of 3 things (with Y):
class Y:X{
}
You don't add a constructor, C# adds one, but it just dumbly calls base(), which doesn't work because there is no constructor in X that takes no args:
class Y:X{
Y():base() { }
}
You add a constructor but leave off the base bit. C# adds it, again just literally as base() - this also doesn't work for the same reason
class Y:X{
Y(int myArg) //c# adds base() in here for you
{
...
}
}
You add a constructor that includes a call to base and because you know your base class only has a constructor with a string arg, you pass one:
class Y:X{
Y(int myArg) : base("hello")
{
...
}
}
So you're in scenario 2, and you either need to:
Add a no-arg constructor to the base class so that c#'s auto-inserted stuff works or,
Add a call to base(...) with a suitable argument, to stop C# from putting a base() in
I've left out access modifiers from code in this answer for clarity of demonstrating the essential point. Whether a constructor is accessible or not can also have a bearing on all this, but I deemed it out of scope

how to log the function calls without calling logger functions inside every function

I am logging the function calls into a log file.
I am using log4Net for the same
public Registration Check(Registration registration)
{
loggingProvider.Entry();
//Some code Here
loggingProvider.Exit();
return something;
}
Now if i have to make an entry of a function call i have to manually add loggingProvider.Entry() inside every function.
Is there a way where I can log all function calls happening inside a given namespace with minimal LOC? Like writing a function in just one place which will log all functions calls happening?
I tried to get the name of the function being called from the constructor/destructor using the stacktrace and log it but its not possible.
Please provide me any alternate way to get the function names that are being called without manually adding log function inside each and every function.
Postsharp would be able to help with this.
http://www.postsharp.net/
Look at injecting behaviour before and after method invocation on http://doc.postsharp.net/method-decorator
As an example, this was taken from their site
[Serializable]
public sealed class TraceAttribute : OnMethodBoundaryAspect
{
// This field is initialized and serialized at build time, then deserialized at runtime.
private readonly string category;
// These fields are initialized at runtime. They do not need to be serialized.
[NonSerialized] private string enteringMessage;
[NonSerialized] private string exitingMessage;
// Default constructor, invoked at build time.
public TraceAttribute()
{
}
// Constructor specifying the tracing category, invoked at build time.
public TraceAttribute(string category)
{
this.category = category;
}
// Invoked only once at runtime from the static constructor of type declaring the target method.
public override void RuntimeInitialize(MethodBase method)
{
string methodName = method.DeclaringType.FullName + method.Name;
this.enteringMessage = "Entering " + methodName;
this.exitingMessage = "Exiting " + methodName;
}
// Invoked at runtime before that target method is invoked.
public override void OnEntry(MethodExecutionArgs args)
{
Trace.WriteLine(this.enteringMessage, this.category);
}
// Invoked at runtime after the target method is invoked (in a finally block).
public override void OnExit(MethodExecutionArgs args)
{
Trace.WriteLine(this.exitingMessage, this.category);
}
}
Methods that need to be traced(logged in your case) can be decorated by using [Trace], it should also be possible to create a class level aspect, where you can decorate the class that should have the logging associated, although I haven't done that myself.

C# VS error: Class does not contain a constructor (even when adding one in the class itself)

On VS C# Express, I get this error when running the code below:
'myComponent.SettingsComponentAttributes' does not contain a
constructor that takes 1 arguments.
I have tried adding a constructor in the class itself but the same message applied to the new constructor:
public override void CreateAttributes()
{
m_attributes = new SettingsComponentAttributes(this);
}
public SettingsComponentAttributes(SettingsComponentAttributes obj)
{
}
Your class doesn't declare any constructors, therefore it's equivalent to having a single parameterless constructor:
public SettingsComponentAttributes()
{
}
You're trying to pass an argument (this) into the constructor - which isn't going to work. You'll need to either change your constructor call, or declare an appropriate constructor.
You should also look at the error message carefully and work out why you needed to ask on Stack Overflow. Which bit of the message wasn't clear to you? Revise that aspect of your C# knowledge. Understanding error messages is a very important part of being a good developer, and this one is fairly clear:
You're trying to use a constructor with 1 argument
No such constructor exists
Default constructors are parameterless, so if you want to create a constructor which accepts one argument you have to create it yourself
Something like this
public class SettingsComponentAttributes : GH_ComponentAttributes
{
public override void CreateAttributes()
{
m_attributes = new SettingsComponentAttributes(this);
}
public SettingsComponentAttributes(SettingsComponentAttributes obj)
{
// Do your fancy work here
}
}
You need to create a class constructor that takes 1 arguement, e.g.:
public SettingsComponentAttributes(SettingsComponentAttributes other)
{
// Initialise.
}
You haven't got a constructor that takes 1 argument
public SettingsComponentAttributes(int i)

Can somebody explain this C# constructor syntax - public Class1(Class 2 Obj) : this(obj.ToString())?

Here is the code:
class Class1
{
private Class2 object;
public Class1(Class2 obj) : this(obj.ToString())
{
this.object = obj;
}
}
More specifically, what does the : this part do.
The :this(obj.ToString) causes the constructor code for the constructor defined taking a string parameter to run first. Once it runs, then the constructor code (setting this.object = obj) is executed.
This is covered in MSDN's page on Constructors (the last example set).
Note that, in your code above, as written, this will cause a compiler error. You would also need to have a constructor like the following:
public Class1(string str) // Constructor taking a string, though it could be non-public
{
// Do something with str
}
With this constructor in place, it will get called, perform it's initialization steps, then the first constructor (which sets this.object) will run.
: this(obj.ToString()) calls overloaded version of constructor from same class.
It means that somewhere in this class you have another constructor which takes string as parameter and will be executed alongside current constructor.
class A
{
public A(Class2 obj): this(obj.ToString()) // execute A(string text)
{
// your code
}
public A(string text)
{
// your code
}
}
Class 1 will have another constructor that takes a string parameter.
It calls the constructor that matches that syntax. In your case, I'm assuming there's a constructor that takes a string argument somewhere:
public Class1(string s)
{
}

Implementation Problem with Static Sealed Class

I have a Sealed class in C#, which already exists and all methods are static.
It does some file operations with xml file. The file name till today was hardcoded into source.
Now the requirement needs to keep it in Configuration file.
The problem is:
Since class is extract, i need to expose some static 'Initialize' method to assign filename to some local static filename variable, which will replace hardcoded string.
So, i always have to make sure, Initialize is called first and then later method.
So, the better way is to have constructor, which i cant write.
I want a better way to do this ensuring type safety.
If the filename field is static, you could make it a property or method and make sure the getter does the work of initializing it from the configuration file if it is not already initialized...
That way you don't have to explicitly initialize the class via a method you can have the access to the property itself initialize the value.
Something like below..
static string FileName { get { return (_field ?? _field = GetFileName()); } }
static string GetFileName() { /* TODO: Return filename from config */ }
Why can't you use a static constructor?
You could write a static constructor to initialize your paths before the static members are referenced.
More info can be found here
If the class itself doesn't know how to access the config I'd use a one time setter:
private static string _filename;
public static string Filename
{
get
{
if(_filename==null)
throw new InvalidOperationException("Filename not set");
return _filename;
}
set
{
if(_filename!=null)
throw new InvalidOperationException("Filename set twice");
_filename=value;
}
}
Or if the class can access the config directly it's even easier:
private static readonly string Filename;
static MyClassName()
{
Filename=GetFilenameFromConfig();
}
Just initialize it in a static constructor.
Assuming the configuration file path is known (i.e. the class takes no formal arguments), then a static constructor might help.
You could change your current class from something like:-
public static Foo
{
public static void Execute()
{
const string FileName = "foo.xml";
// ...
}
}
To something like
public static Foo
{
public static void Execute()
{
Execute("foo.xml");
}
public static void Execute(string fileName)
{
// ...
}
}
Current clients of the code can continue to use the original method (hard coded file name) and any new clients which have the file name as a configuration item can use the new method which takes the file name as a parameter. Or, if you have decided that all client should use the new method, then you can change them to do that and remove the old method.
The simplest option would be to add a static constructor. That will be executed before any other code:
public static class Foo
{
static Foo()
{
// Initialization code
}
// Other methods which can depend on initialization code having run
}
As I say, this is the simplest - in terms of changes to your existing code. However, code like this tends to be hard to debug, and if you have a lot of static constructors which depend on each other, you can get into some tricky situations (particularly if you have cyclic dependencies). For an example of this, watch the "C# Puzzlers" video from NDC 2010 - an excellent talk given by Eric Lippert and Neal Gafter.

Categories