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
Related
I can't say I tried everything as I am not too much in to ASP.NET. I even tried googling but I was unsure what to search.
I haev several classes in ASP.NET as I am making a billing software for a reputed PSU. The project is deployed and is working fine.
Now the client requires the numbers in the bills to be currency formatted in reports but to be unformatted (numeric) in certain other things.
As I already have classes which have exposed property as double, I want my developers to give something very easy so that they can do it rapidly.
Something like : myclassobj.EnergyBillAmount().toCurreny("en-IN") or something like this.
Any suggestions?
All you need is Extension Method
public static class FormatExtensions
{
public static string ToCurrency(this double value, string culture)
{
//return converted value
}
}
Use Extension Methods
Create a class as below
namespace ExtensionMethods
{
public static class MyExtensions
{
public static int ToCurrency(this Int val)
{
//Code logic
}
}
}
And do a
using ExtensionMethods;
where you want to call it
and use like
int s = 100;
int i = s.ToCurrency();
Hope it helps....
You should write extension method for that.
Instead of double you should use decimal for currency.
Do you really need an extension method for this:
string c = 1234.56m.ToString("C", CultureInfo.CreateSpecificCulture("en-IN"));
Result: ₹ 1,234.56
myclassobj.EnergyBillAmount().ToString("C2", yourCulture);
i got few line of code where configure method is calling and passing just the string value but ConfigureWith function expect delegate. can anyone help me to understand how ConfigureWith() method will work. thanks
MailTemplate
.ConfigureWith(mt => mt.MailBody = "hello world")
.ConfigureWith(mt => mt.MailFrom = "rdingwall#gmail.com")
.DoSomeOtherStuff()
.Build();
The implementation for this would be:
public class MailTemplate
{
// regular auto properties
public string MailFrom { get; set; }
public string MailBody { get; set; }
public MailTemplate ConfigureWith(Action<MailTemplate> func)
{
func(this);
return this;
}
}
As written it seems entirely pointless, you may as well just set the property on the MailTemplate directly.
Typically in a fluent builder like this you would save the Actions being passed in with each ConfigureWith call and then execute them later.
It might help if you explain in more detail what you hope to achieve with the fluent syntax you are creating. As written it also will not compile since the first call expects a static method. Can you show the real code?
You might also want to look at other answers on StackOverflow regarding fluent methods (e.g. Tips for writing fluent interfaces in C# 3)
I see that the example above is from an answer to a different question you asked earlier. I'm still not entirely sure what you're trying to do, and as Ian Mercer suggested, it's pretty pointless as written. But if you're just trying to understand what it does, then let's first get a working example:
using System;
namespace ScratchApp
{
internal class Program
{
private static void Main(string[] args)
{
var mailTemplate = BuildMailTemplate(
mt => mt.MailBody = "hello world",
mt => mt.MailFrom = "rdingwall#gmail.com");
}
private static MailTemplate BuildMailTemplate(
Action<MailTemplate> configAction1,
Action<MailTemplate> configAction2)
{
var mailTemplate = new MailTemplate();
mailTemplate.ConfigureWith(configAction1)
.ConfigureWith(configAction2)
.DoSomeOtherStuff()
.Build();
return mailTemplate;
}
}
public class MailTemplate
{
public string MailFrom { get; set; }
public string MailBody { get; set; }
public MailTemplate DoSomeOtherStuff()
{
// Do something
return this;
}
public MailTemplate Build()
{
// Build something
return this;
}
public MailTemplate ConfigureWith(Action<MailTemplate> func)
{
func(this);
return this;
}
}
}
This is as pointless as before, but it builds. What's happening when you're calling .ConfigureWith() is that instead of passing a normal value, you're passing it a function. In the example above, I'm actually declaring the functions as parameters that get passed into the BuildMailTemplate() method, and which in turn get executed when the template is being built and configured. You can get a feel for how it works by stepping through the code, line-by-line (e.g., F11 in Visual Studio), and setting breakpoints in the lambda expressions themselves, and then looking at the call stack.
If you're confused about the syntax for lambdas - arrow syntax is indeed a bit complex when you're first getting used to it - then feel free to check out the MSDN article on it, or just Google "c# lambdas" to your heart's delight.
I really wanted to just use
Class MyClasses
{
public string mwaAHA = "here";
//and then use it like this:
static void testStringhere()
{
console.writeline(mwaAHA);
}
}
I'm doing something wrong can someone demo the eaist way I can make a few strings and use them in any void?
Since your testStringhere() is static, it only has access to other static members residing in the same scope.
To solve your issue in this case use
public static string mwaAHA = "here";
The answer above is right, but it should probably also have a private and a const..something like:
private const string str = "here";
I've never really questioned this before until now. I've got an input model with a number of fields, I wanted to present the string names of the properties through the input model so that my Grid can use them:
public class SomeGridRow
{
public string Code { get;set; }
public string Description { get;set; }
public const string Code = "Code";
}
Obviously, this gives the error:
The type 'SomeGridRow' already
contains a definition for 'Code'
Why can the CLR not cope with two properties of the same name which are, in my eyes, separate?
string code = gridRow.Code; // Actual member from instantiated class
string codeField = SomeGridRow.Code; // Static/Const
I'm now just using a child class called Fields within my inputs now, so I can use SomeGridRow.Fields.Code. It's a bit messy, but it works.
Because you can also access static (or, non-instance in this case) properties in the same way (inside the same class), and it would be a bit confusing, for example:
public class SomeGridRow
{
public string Code { get;set; }
public const string Code = "Code";
public void MyMethod() {
var thing = Code; //what would this reference?
}
}
Because both this:
public class SomeGridRow
{
public string Code { get;set; }
public void MyMethod() {
var thing = Code; //what would this reference?
}
}
And this:
public class SomeGridRow
{
public const string Code = "Code";
public void MyMethod() {
var thing = Code; //what would this reference?
}
}
are valid ways to access properties, static or not. It doesn't answer the "why can't I?" question, but more of the why it's not allowed...it would be far too ambiguous IMO.
It probably could, but the designers of C# wanted to avoid ambiguities that can come from such use (abuse?) of language features.
Such code would end up being confusing and ambiguous to users (did I want the instance or the static method call?, Which one is right?).
In addition to the points already made about ambiguity, i would say that the naming needs to be relooked in such a case.
If two variables / fields having the exact same name in the same context i.e class but different values to me sounds more like a naming issue.
If they are exactly same, you dont need 2 fields.
If they are slightly different, you should have more accurate names.
In some other languages with a similar syntax, one can access a static member through an instance. So you could access both string.Empty and "abc".Empty.
C# doesn't allow this (though it does sort of from inside the class or a derived class, in that you can omit the class name for a static member and can omit this for an instance member), primarily to avoid confusion (I find it more handy than confusion tbh, but that's just me, I like switch fall-through too so what do I know).
Having introduced a stricter rule to allow for less ambiguity, it would be counterproductive to allow a new looser rule on the back of it that allowed for more. Think how many "why must I use this with property X but not property Y?" questions SO would have if it was allowed (we'd have to force this with property X to be clear we meant the instance member).
I'm not sure if I am abusing Enums here. Maybe this is not the best design approach.
I have a enum which declares the possible parameters to method which executes batch files.
public enum BatchFile
{
batch1,
batch2
}
I then have my method:
public void ExecuteBatch(BatchFile batchFile)
{
string batchFileName;
...
switch (batchFile)
{
case BatchFile.batch1:
batchFileName = "Batch1.bat";
break;
case BatchFile.batch2:
batchFileName = "Batch2.bat";
break;
default:
break;
}
...
ExecuteBatchFile(batchFileName);
}
So I was wondering if this is sound design.
Another option I was thinking was creating a Dictionary<> in the constructor like this:
Dictionary<BatchFile, String> batchFileName = new Dictionary<BatchFile, string>();
batchFileName.Add(BatchFile.batch1, "batch1.bat");
batchFileName.Add(BatchFile.batch2, "batch2.bat");
Then instead of using a switch statement I would just go:
public void ExecuteBatch(BatchFile batchFile)
{
ExecuteBatchFile(batchFileName[batchFile]);
}
I'm guessing the latter is the better approach.
I'd probably go for a design along these lines:
public interface IBatchFile
{
void Execute();
}
public class BatchFileType1 : IBatchFile
{
private string _filename;
public BatchFileType1(string filename)
{
_filename = filename;
}
...
public void Execute()
{
...
}
}
public class BatchFileType2 : IBatchFile
{
private string _filename;
public BatchFileType2(string filename)
{
_filename = filename;
}
...
public void Execute()
{
...
}
}
In fact, I'd extract any common functionality into a BatchFile base class
What if you suddenly need a third batch file? You have to modify your code, recompile your library and everybody who uses it, has to do the same.
Whenever I find myself writing magic strings that might change, I consider putting them into an extra configuration file, keeping the data out of the code.
I would personally use a static class of constants in this case:
public static class BatchFiles
{
public const string batch1 = "batch1.bat";
public const string batch2 = "batch2.bat";
}
If you want to use an enum then you may want to consider utilising attributes so you can store additional inforation (such as the file name) against the elements.
Here's some sample code to demonstrate how to declare the attributes:
using System;
public enum BatchFile
{
[BatchFile("Batch1.bat")]
batch1,
[BatchFile("Batch2.bat")]
batch2
}
public class BatchFileAttribute : Attribute
{
public string FileName;
public BatchFileAttribute(string fileName) { FileName = fileName; }
}
public class Test
{
public static string GetFileName(Enum enumConstant)
{
if (enumConstant == null)
return string.Empty;
System.Reflection.FieldInfo fi = enumConstant.GetType().GetField(enumConstant.ToString());
BatchFileAttribute[] aattr = ((BatchFileAttribute[])(fi.GetCustomAttributes(typeof(BatchFileAttribute), false)));
if (aattr.Length > 0)
return aattr[0].FileName;
else
return enumConstant.ToString();
}
}
To get the file name simply call:
string fileName = Test.GetFileName(BatchFile.batch1);
I think the latter approach is better because it separates out concerns. You have a method which is dedicated to associating the enum values with a physical path and a separate method for actually executing the result. The first attempt mixed these two approaches slightly.
However I think that using a switch statement to get the path is also a valid approach. Enums are in many ways meant to be switched upon.
Using enums is ok if you don't need to add new batch files without recompiling / redeploying your application... however I think most flexible approach is to define a list of key / filename pairs in your config.
To add a new batch file you just add it to the config file / restart / tell your user the key. You just need to handle unknown key / file not found exceptions.
Is it really necessary that ExecuteBatch works on limited number of possible file names only?
Why don't you just make it
public void ExecuteBatch(string batchFile)
{
ExecuteBatchFile(batchFile);
}
The problem with the latter case is if something passed an invalid value that is not inside the dictionary. The default inside the switch statement provides an easy way out.
But...if you're enum is going to have a lot of entries. Dictionary might be a better way to go.
Either way, I'd recommend some way to provide protection of the input value from causing a bad error even in ammoQ's answer.
The second approach is better, because it links the batch file objects (enums) with the strings..
But talking about design, it would not be very good to keep the enum and the dictionary separate; you could consider this as an alternative:
public class BatchFile {
private batchFileName;
private BatchFile(String filename) {
this.batchFileName = filename;
}
public const static BatchFile batch1 = new BatchFile("file1");
public const static BatchFile batch2 = new BatchFile("file2");
public String getFileName() { return batchFileName; }
}
You can choose to keep the constructor private, or make it public.
Cheers,
jrh.
The first solution (the switch) is simple and straight forward, and you really don't have to make it more complicated than that.
An alternative to using an enum could be to use properties that returns instances of a class with the relevant data set. This is quite expandable; if you later on need the Execute method to work differently for some batches, you can just let a property return a subclass with a different implementation and it's still called in the same way.
public class BatchFile {
private string _fileName;
private BatchFile(string fileName) {
_fileName = fileName;
}
public BatchFile Batch1 { get { return new BatchFile("Batch1.bat"); } }
public BatchFile Batch2 { get { return new BatchFile("Batch2.bat"); } }
public virtual void Execute() {
ExecuteBatchFile(_fileName);
}
}
Usage:
BatchFile.Batch1.Execute();