I have some -really long- string literals in my application. Does it differ to define them in a method like:
public string DoSomething()
{
string LongString = "...";
// ...
}
or as a const field in the lass like:
private const string LongString = "...";
public string DoSomething()
{
// ...
}
The DoSomething() method will be called many many times, is the LongString created and destroyed each time if I define it inside the method, or the compiler takes care?
String literals get interned by the CLR. Effectively meaning they will be created only once.
There is no difference between the two, the string will not be created and destroyed many times in the method. .NET uses string interning, so distinct string literals are only defined once.
In your first example, it would only be available in the function. In your second it would be available to other functions in that same class.
Related
Assuming I will need to access the values contained within a given file a small number of times, from different methods, can I include some sort of boolean value within a method to determine whether or not it is appropriate to call the file?
Lets say I have the file config.cfg. In that file, there are three values:
string/name>max|
bool/adult>yes|
int/age>20|
The method getUserName() returns the value of "max". It does this by calling the file:
using (StreamReader reader = new StreamReader(path))
{
//get line beginning with string/name here
return //string value containing name
}
Let's assume I need to use the value of name several times, as well as the values isAdult and clientAge. Rather than accessing the file over and over again, it could be much easier to save the requested value in some form of static variable. However, this variable still needs to be changed in value at least once, when the method is first called.
Can I do this inside the method getUserName()?
Furthermore, is this idea even possible within the bounds of OOP? Is it a similar concept to Prefetch?
It really looks to me that you need to access a field in a lazy way (i.e. only if needed, when needed). If so .NET has Lazy class for such cases which also provides thread safety out of the box:
public static Lazy<string> Name { get; } = new Lazy<string>(() => ReadNameFromFile());
Lazy will also ensure that you only create value once (i.e. call initiailization method) and on later calls it will simply return already retrieved value.
Create a static class. Something like this:
public static class ClientConfig{
public static string Name{get;set;}
public static bool IsAdult{get;set;}
public static int Age{get;set;}
public static void Load(){
// load your values
// ClientConfig.Name = name from file etc.
}
public static void Save(string newName, int age, bool value){
// save your values to the config file
}
}
And call ClientConfig.Load() first time when your app starts, for example (or whenever you need to retrieve config data)
public static class Abc
{
public const string Placeholder = "{$content}";
public const string Pattern = $"<div class=\"embed-responsive\">{Placeholder}</div>";
}
How to correctly solve this to avoid breaching DRY (Dont repeat yourself)? I know I can use static readonly, but then it is a bit of a different thing (even though it works..). I think there should be better way? Or is there really not?
While you cannot call a method to initialize a constant value, it is allowed to use operators. If you need to create a constant that contains another constant value, use the plus operator to concatenate string values.
public static class Abc
{
public const string Placeholder = "{$content}";
public const string Pattern = "<div class=\"embed-responsive\">" + Placeholder + "</div>";
}
Extending core classes in javascript is dead easy. I get the impression it's not quite so easy in C#. I was wanting to add some things to the String class so that I could do stuff like:
string s = "the cat's mat sat";
string sql = s.smartsingleQuote();
thus giving me
the cat''s mat sat
Is that even feasible, or do I have to write a function for that?
Yes it is possible using Extension Methods - MSDN
Here is a sample code.
public static class Extns
{
public static string smartsingleQuote(this string s)
{
return s.Replace("'","''");
}
}
Disclaimer : Not tested.
Yes you can do this, with an extension method. It'll look something like that:
public static class NameDoesNotMatter {
public static string smartSingleQuote(this string s) {
string result = s.Replace("'","''");
return result;
}
}
The magic is the keyword "this" in front of the first argument. Then you can write your code and it'll work:
string s = "the cat's mat sat";
string sql = s.smartsingleQuote();
You cannot accomplish exactly what you are talking about as the string class is sealed
You can accomplish the aesthetic of this by creating an extension method
public static class StringExtensions
{
public static string SmartSingleQuote(this string str)
{
//Do stuff here
}
}
The this keyword in the parameter allows you to take that parameter and put it in front of the method name for easier chaining like you requested done in your question. This, however, is equivalent to:
StringExtensions.SmartSingleQuote(s);
It just depends on your preference at that point :)
Here is a good SO answer on extension methods
C# 4 introduced a feature called named arguments which is especially useful in scenarios like
int RegisterUser(string nameFirst, string nameLast, string nameMiddle, string email)
Is there a way to force using named arguments? Maybe some attribute to apply to a method or a compiler switch I'm not aware of? I guess it can be done with code inspector tools but just want to know if there is other way.
p.s.
For those interested why one may need it and why not just use a class/struct to utilize object initializers there are scenarios when it's impossible. Like calls to libraries not in your control or weird code conventions you have to obey.
It's possible to force the callers to always use named args. I wouldn't do this in most circumstances because it's rather ugly, but it depends on how badly safe method usage is needed.
Here is the solution:
int RegisterUser(
#if DEBUG
int _ = 0,
#endif
string nameFirst = null,
string nameLast = null,
string nameMiddle = null,
string email = null) { /*...*/ }
The first parameter is a dummy that shouldn't be used (and is compiled away in Release for efficiency). However, it ensures that all following parameters have to be named.
Valid usage is any combination of the named parameters:
RegisterUser();
RegisterUser(nameFirst: "Joe");
RegisterUser(nameFirst: "Joe", nameLast: "Smith");
RegisterUser(email: "joe.smith#example.com");
When attempting to use positional parameters, the code won't compile.
No, not in the C# language. It will always accept positional parameters if all the parameters are supplied.
You could build a custom FxCop rule or an StyleCop rule to enforce this - as pointed out in the comments, it is likely a StyleCop rule you would be interested in (thanks to Kris).
Sorry for a shameless plug!
I implemented a Roslyn analyzer to enforce using named arguments for a method.
So if you install the RequireNamedArgs analyzer and add a special comment before a method that should be invoked with named arguments:
//[RequireNamedArgs]
int RegisterUser(string nameFirst, string nameLast, string nameMiddle, string email)
The analyzer will emit an error if a caller attempts to use positional arguments instead of named.
Take a look at it in action:
If you decide to give it a go -- do so at your own risk :)
I've also sought a way to force named arguments. Optional parameters can be dangerous, especially if you have multiple parameters of the same type. Overloads are almost always a safer solution, but there are times when you have a method that can take many combination of arguments, so creating 20 overloads to account for ever possibility is overkill.
In extreme situations where it is of the utmost importance that arguments be named at all times, I will create an argument class with no defined constructor. In your case, you could do this:
public class UserRegistrationArguments
{
public string nameFirst { get; set; }
public string nameLast { get; set; }
public string nameMiddle { get; set; }
public string email { get; set; }
}
Call it like this:
RegisterUser(new UserRegistrationArguments { nameFirst = "Bob", nameLast = "Slob" });
You could also simplify it like this:
public class UserRegistrationArguments
{
public string nameMiddle { get; set; }
public string email { get; set; }
}
int RegisterUser(string nameFirst, string nameLast, UserRegistrationArguments args = null)
...and do this:
RegisterUser("Bob", "Slob", new UserRegistrationArguments { nameMiddle = "Teh" });
This way, you only have one optional parameter and that's for your optional parameters.
Edit: Maybe I didn't read the OP correctly. You're not using optional arguments? If not then this answer probably doesn't help you.
I'm using another method. In my setup I have 1 parameter which I always expect, then come a bunch of optional strings which I really want to be sure the user chose actively. So my first string in this list is a "trap" value, which if set, throws an error. Like this:
public HtmlString Toolbar(DynamicEntity target = null, string dontRelyOnParameterOrder = Constants.RandomProtectionParameter, string actions = null, string contentType = null, object prefill = null)
{
if (!Enabled) return null;
protectAgainstMissingParameterNames(dontRelyOnParameterOrder);
var toolbar = new ItemToolbar(target, actions, contentType, prefill);
return new HtmlString(toolbar.Toolbar);
}
private void protectAgainstMissingParameterNames(string criticalParameter)
{
if(criticalParameter != Constants.RandomProtectionParameter)
throw new Exception("when using the toolbar command, please use named parameters - otherwise you are relying on the parameter order staying the same.");
}
Hope you like it :)
I am writing a class. I have encountered the problem in the title.
Here is the code:
class delivery
{
private string strDeliveryName;
private string strDeliveryAddress;
private string strDeliveryDay;
private string strDeliveryTime;
private string strDeliveryMeal;
private string strDeliveryInstructions;
private string strDeliveryStatus;
}
public delivery(string deliveryName, string deliveryAddress, string deliveryDay, string deliveryTime, string deliveryMeal, string deliveryInstructions, string deliveryStatus)
{
strDeliveryName = deliveryName;
strDeliveryAddress = deliveryAddress;
strDeliveryDay = deliveryDay;
strDeliveryTime = deliveryTime;
strDeliveryMeal = deliveryMeal;
strDeliveryInstructions = deliveryInstructions;
strDeliveryStatus = deliveryStatus;
}
I get the error on the public delivery, any idea why?
Your constructor should be within the brackets of the class definition. On an unrelated note, the convention is to capitalize the first letter of class names.
Your constructor code is not inside the class. Move it inside and all should be fine. :-)
To answer your second question (in the comment), you need to change the name of the constructor to match the name of the class.
This error is because you have declared the function outside of the main class. You should insert your code inside the main class.
I received this error because I accidentally missed an open brace in code above where the error occurred. This meant the class ended prematurely. So if you get this error maybe check that your braces are correct.