I have the following code I am trying to consolidate. (here are two examples) but with this repeated pattern of checking if fields are null then if they are different and if yes, then setting the new value into the old value.
What is the best way to rewrite this to avoid duplication?
if (String.IsNullOrEmpty(f.FirstName))
{
if (exisingPerson.FirstName != f.FirstName)
{
change = true;
exisingPerson.FirstName = f.FirstName;
}
}
if (String.IsNullOrEmpty(f.LastName))
{
if (exisingPerson.LastName != f.LastName)
{
change = true;
exisingPerson.LastName = f.LastName;
}
}
I don't think you can do much to remove the duplication (at least not without introducing reflection which will probably just muddy the code rather than make it clearer).
However you could look at implementing INotifyPropertyChanged which is a standard pattern for notifying about changes to an object instead of the boolean you are currently using:
How to: Implement the INotifyPropertyChanged Interface
If you look at the example code there it also has a certain amount of repetition.
You can use delegates:
public static bool ChangeProperty(Func<Person, string> getter, Action<Person, string> setter, Person person, string value)
{
if (!String.IsNullOrEmpty(value) && !getter(person).Equals(value))
{
setter(person, value);
return true;
}
return false;
}
and call it with lambdas like this:
var barneyRubble = new Person();
change = ChangeProperty(p => p.FirstName, (p, v) => p.FirstName = v, barneyRubble, "Fred");
An even better thing to do would be to put the method in the Person class and eliminate that third parameter altogether, replacing it with this.
Probably overkill, but if you're making a lot of these kind of property changes it might be valuable, and I think it's an interesting pattern anyway.
For just a couple of fields, your code may be the best. Short and simple.
If you're doing this a lot, you could use reflection to iterate through each field in the object, and perform the operation if it's a String.
However, the downside of this is readability. Perhaps you're better off being explicit, and protecting against typos through copy/paste through extensive use of unit tests.
Related
The question is theoretical and I want to understand general difference and performance matter in particular between 2 different definition that give the same result.
I have a class GLProcessingModel that has a reference to a graph (So it has not direct references to the UI). The class has a method that determine of an item has some value (currently my code looks like that):
private bool IsEmployerSuperWorkCover(MPCurrentPayPayItem payItem)
{
return PXSelectJoin<MPPayItem,
InnerJoin<MPPayItemType, On<MPPayItemType.payItemTypeID, Equal<MPPayItem.payItemTypeID>>,
InnerJoin<MPRollupItem, On<MPRollupItem.payItemID, Equal<MPPayItem.payItemID>>,
InnerJoin<MPRollup, On<MPRollup.rollupID, Equal<MPRollupItem.rollupID>>>>>,
Where<MPRollup.name, Equal<Required<MPRollup.name>>,
And<MPRollupItem.payItemID, Equal<Required<MPRollupItem.payItemID>>,
And<MPPayItemType.payItemTypeCD, Equal<Required<MPPayItemType.payItemTypeCD>>>>>>
.Select(Graph, MPPayItem.WORCOVER_AU, payItem.PayItemID, MPPayItemType.EMPLOYER_SUPER)
.AsEnumerable()
.Any();
}
What is the difference if I define the same expression in the different way (or something like that):
PXSelectJoin<MPPayItem, InnerJoin<MPPayItemType, On<MPPayItemType.payItemTypeID, Equal<MPPayItem.payItemTypeID>>,
InnerJoin<MPRollupItem, On<MPRollupItem.payItemID, Equal<MPPayItem.payItemID>>,
InnerJoin<MPRollup, On<MPRollup.rollupID, Equal<MPRollupItem.rollupID>>>>>,
Where<MPRollup.name, Equal<Required<MPRollup.name>>,
And<MPRollupItem.payItemID, Equal<Required<MPRollupItem.payItemID>>,
And<MPPayItemType.payItemTypeCD, Equal<Required<MPPayItemType.payItemTypeCD>>>>>> EmployerSuperWorkCoverQuery;
private bool IsEmployerSuperWorkCover(MPCurrentPayPayItem payItem)
{
if (EmployerSuperWorkCoverQuery == null)
{
EmployerSuperWorkCoverQuery = new PXSelectJoin<MPPayItem, InnerJoin<MPPayItemType, On<MPPayItemType.payItemTypeID, Equal<MPPayItem.payItemTypeID>>,
InnerJoin<MPRollupItem, On<MPRollupItem.payItemID, Equal<MPPayItem.payItemID>>,
InnerJoin<MPRollup, On<MPRollup.rollupID, Equal<MPRollupItem.rollupID>>>>>,
Where<MPRollup.name, Equal<Required<MPRollup.name>>,
And<MPRollupItem.payItemID, Equal<Required<MPRollupItem.payItemID>>,
And<MPPayItemType.payItemTypeCD, Equal<Required<MPPayItemType.payItemTypeCD>>>>>>(Graph);
}
return EmployerSuperWorkCoverQuery.Select(MPPayItem.WORCOVER_AU, payItem.PayItemID, MPPayItemType.EMPLOYER_SUPER)
.AsEnumerable()
.Any();
}
I believe every-time when graph calls the method in the class GLProcessingModel, EmployerSuperWorkCoverQuery will be null and needs to initialize it.
I believe there is better option to define the same behavior. return PXSelectJoin<MPPayItem, ... looks like db connection, sql generation etc and not the best option.
How it changes the caching mechanism?
What is optimal way to implement such behavior with the best performance?
Creating a C# object (dataview) will not significantly impact performance.
There are only two approaches which will yield measurable differences:
Use the low level PXDatabase class for data access instead of
PXSelect.
Use the Prefetch pattern to cache the results.
Reference: https://www.acumatica.com/blog/application-wide-caching-with-slots-and-iprefetchable/
Version 6.0 got a new feature of nameof, but I can't understand the purpose of it, as it just takes the variable name and changes it to a string on compilation.
I thought it might have some purpose when using <T> but when I try to nameof(T) it just prints me a T instead of the used type.
Any idea on the purpose?
What about cases where you want to reuse the name of a property, for example when throwing exception based on a property name, or handling a PropertyChanged event. There are numerous cases where you would want to have the name of the property.
Take this example:
switch (e.PropertyName)
{
case nameof(SomeProperty):
{ break; }
// opposed to
case "SomeOtherProperty":
{ break; }
}
In the first case, renaming SomeProperty will cause a compilation error if you don't change both the property definition and the nameof(SomeProperty) expression. In the second case, renaming SomeOtherProperty or altering the "SomeOtherProperty" string will result in silently broken runtime behavior, with no error or warning at build time.
This is a very useful way to keep your code compiling and bug free (sort-of).
(A very nice article from Eric Lippert why infoof didn't make it, while nameof did)
It's really useful for ArgumentException and its derivatives:
public string DoSomething(string input)
{
if(input == null)
{
throw new ArgumentNullException(nameof(input));
}
...
Now if someone refactors the name of the input parameter the exception will be kept up to date too.
It is also useful in some places where previously reflection had to be used to get the names of properties or parameters.
In your example nameof(T) gets the name of the type parameter - this can be useful too:
throw new ArgumentException(nameof(T), $"Type {typeof(T)} does not support this method.");
Another use of nameof is for enums - usually if you want the string name of an enum you use .ToString():
enum MyEnum { ... FooBar = 7 ... }
Console.WriteLine(MyEnum.FooBar.ToString());
> "FooBar"
This is actually relatively slow as .Net holds the enum value (i.e. 7) and finds the name at run time.
Instead use nameof:
Console.WriteLine(nameof(MyEnum.FooBar))
> "FooBar"
Now .Net replaces the enum name with a string at compile time.
Yet another use is for things like INotifyPropertyChanged and logging - in both cases you want the name of the member that you're calling to be passed to another method:
// Property with notify of change
public int Foo
{
get { return this.foo; }
set
{
this.foo = value;
PropertyChanged(this, new PropertyChangedEventArgs(nameof(this.Foo));
}
}
Or...
// Write a log, audit or trace for the method called
void DoSomething(... params ...)
{
Log(nameof(DoSomething), "Message....");
}
Another use-case where nameof feature of C# 6.0 becomes handy - Consider a library like Dapper which makes DB retrievals much easier. Albeit this is a great library, you need to hardcode property/field names within query. What this means is that if you decide to rename your property/field, there are high chances that you will forget to update query to use new field names. With string interpolation and nameof features, code becomes much easier to maintain and typesafe.
From the example given in link
without nameof
var dog = connection.Query<Dog>(
"select Age = #Age, Id = #Id",
new {Age = (int?) null, Id = guid});
with nameof
var dog = connection.Query<Dog>(
$"select {nameof(Dog.Age)} = #Age, {nameof(Dog.Id)} = #Id",
new {Age = (int?) null, Id = guid});
Your question already expresses the purpose. You must see this might be useful for logging or throwing exceptions.
For example:
public void DoStuff(object input)
{
if (input == null)
{
throw new ArgumentNullException(nameof(input));
}
}
This is good. If I change the name of the variable, the code will break instead of returning an exception with an incorrect message.
Of course, the uses are not limited to this simple situation. You can use nameof whenever it would be useful to code the name of a variable or property.
The uses are manifold when you consider various binding and reflection situations. It's an excellent way to bring what were run time errors to compile time.
The most common use case I can think of is when working with the INotifyPropertyChanged interface. (Basically everything related to WPF and bindings uses this interface)
Take a look at this example:
public class Model : INotifyPropertyChanged
{
// From the INotifyPropertyChanged interface
public event PropertyChangedEventHandler PropertyChanged;
private string foo;
public String Foo
{
get { return this.foo; }
set
{
this.foo = value;
// Old code:
PropertyChanged(this, new PropertyChangedEventArgs("Foo"));
// New Code:
PropertyChanged(this, new PropertyChangedEventArgs(nameof(Foo)));
}
}
}
As you can see in the old way we have to pass a string to indicate which property has changed. With nameof we can use the name of the property directly. This might not seem like a big deal. But image what happens when somebody changes the name of the property Foo. When using a string the binding will stop working, but the compiler will not warn you. When using nameof you get a compiler error that there is no property/argument with the name Foo.
Note that some frameworks use some reflection magic to get the name of the property, but now we have nameof this is no longer neccesary.
Most common usage will be in input validation, such as
//Currently
void Foo(string par) {
if (par == null) throw new ArgumentNullException("par");
}
//C# 6 nameof
void Foo(string par) {
if (par == null) throw new ArgumentNullException(nameof(par));
}
In first case, if you refactor the method changing par parameter's name, you'll probably forget to change that in the ArgumentNullException. With nameof you don't have to worry about that.
See also: nameof (C# and Visual Basic Reference)
The ASP.NET Core MVC project uses nameof in the AccountController.cs and ManageController.cs with the RedirectToAction method to reference an action in the controller.
Example:
return RedirectToAction(nameof(HomeController.Index), "Home");
This translates to:
return RedirectToAction("Index", "Home");
and takes takes the user to the 'Index' action in the 'Home' controller, i.e. /Home/Index.
Let's say you need to print the name of a variable in your code. If you write:
int myVar = 10;
print("myVar" + " value is " + myVar.toString());
and then if someone refactors the code and uses another name for myVar, he/she would have to look for the string value in your code and change it accordingly.
Instead, if you write:
print(nameof(myVar) + " value is " + myVar.toString());
It would help to refactor automatically!
The MSDN article lists MVC routing (the example that really clicked the concept for me) among several others. The (formatted) description paragraph reads:
When reporting errors in code,
hooking up model-view-controller (MVC) links,
firing property changed events, etc.,
you often want to
capture the string name of a method. Using nameof helps keep your code
valid when renaming definitions.
Before you had to use string literals
to refer to definitions, which is brittle when renaming code elements
because tools do not know to check these string literals.
The accepted / top rated answers already give several excellent concrete examples.
As others have already pointed out, the nameof operator does insert the name that the element was given in the sourcecode.
I would like to add that this is a really good idea in terms of refactoring since it makes this string refactoring safe. Previously, I used a static method which utilized reflection for the same purpose, but that has a runtime performance impact. The nameof operator has no runtime performance impact; it does its work at compile time. If you take a look at the MSIL code you will find the string embedded. See the following method and its disassembled code.
static void Main(string[] args)
{
Console.WriteLine(nameof(args));
Console.WriteLine("regular text");
}
// striped nops from the listing
IL_0001 ldstr args
IL_0006 call System.Void System.Console::WriteLine(System.String)
IL_000C ldstr regular text
IL_0011 call System.Void System.Console::WriteLine(System.String)
IL_0017 ret
However, that can be a drawback if you plan to obfuscate your software. After obfuscation the embedded string may no longer match the name of the element. Mechanisms that rely on this text will break. Examples for that, including but not limited to are: Reflection, NotifyPropertyChanged ...
Determining the name during runtime costs some performance, but is safe for obfuscation. If obfuscation is neither required nor planned, I would recommend using the nameof operator.
The purpose of the nameof operator is to provide the source name of the artifacts.
Usually the source name is the same name as the metadata name:
public void M(string p)
{
if (p == null)
{
throw new ArgumentNullException(nameof(p));
}
...
}
public int P
{
get
{
return p;
}
set
{
p = value;
NotifyPropertyChanged(nameof(P));
}
}
But this may not always be the case:
using i = System.Int32;
...
Console.WriteLine(nameof(i)); // prints "i"
Or:
public static string Extension<T>(this T t)
{
return nameof(T); returns "T"
}
One use I've been giving to it is for naming resources:
[Display(
ResourceType = typeof(Resources),
Name = nameof(Resources.Title_Name),
ShortName = nameof(Resources.Title_ShortName),
Description = nameof(Resources.Title_Description),
Prompt = nameof(Resources.Title_Prompt))]
The fact is that, in this case, I didn't even need the generated properties to access the resources, but now I have a compile time check that the resources exist.
The purpose of nameof is refactoring. For example when you change the name of a class to which you refer to through nameof somewhere else in your code you will get a compilation error which is what you want. If you didn't use nameof and had just a plain string as a reference you'd have to fulltext search for the name of the class in order to change it. That's a pain in the bottom. With nameof you can rest easy, build, and get all the cases for change automatically in your IDE.
Another use case of nameof is to check tab pages, instead of checking the index you can check the Name property of the tabpages as follow:
if(tabControl.SelectedTab.Name == nameof(tabSettings))
{
// Do something
}
Less messy :)
I find that nameof increases the readability of very long and complex SQL statements in my applications. It makes the variables stand out of that sea of strings and eliminates your job of figuring out where the variables are used in your SQL statements.
public bool IsFooAFoo(string foo, string bar)
{
var aVeryLongAndComplexQuery = $#"SELECT yada, yada
-- long query in here
WHERE fooColumn = #{nameof(foo)}
AND barColumn = #{nameof(bar)}
-- long query here";
SqlParameter[] parameters = {
new SqlParameter(nameof(foo), SqlDBType.VarChar, 10){ Value = foo },
new SqlParameter(nameof(bar), SqlDBType.VarChar, 10){ Value = bar },
}
}
One of the usage of nameof keyword is for setting Binding in wpf programmatically.
to set Binding you have to set Path with string, and with nameof keyword, it's possible to use Refactor option.
For example, if you have IsEnable dependency property in your UserControl and you want to bind it to IsEnable of some CheckBox in your UserControl, you can use these two codes:
CheckBox chk = new CheckBox();
Binding bnd = new Binding ("IsEnable") { Source = this };
chk.SetBinding(IsEnabledProperty, bnd);
and
CheckBox chk = new CheckBox();
Binding bnd = new Binding (nameof (IsEnable)) { Source = this };
chk.SetBinding(IsEnabledProperty, bnd);
It's obvious the first code can't refactor but the secend one...
Previously we were using something like that:
// Some form.
SetFieldReadOnly( () => Entity.UserName );
...
// Base form.
private void SetFieldReadOnly(Expression<Func<object>> property)
{
var propName = GetPropNameFromExpr(property);
SetFieldsReadOnly(propName);
}
private void SetFieldReadOnly(string propertyName)
{
...
}
Reason - compile time safety. No one can silently rename property and break code logic. Now we can use nameof().
It has advantage when you use ASP.Net MVC. When you use HTML helper to build some control in view it uses property names in name attribure of html input:
#Html.TextBoxFor(m => m.CanBeRenamed)
It makes something like that:
<input type="text" name="CanBeRenamed" />
So now, if you need to validate your property in Validate method you can do this:
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (IsNotValid(CanBeRenamed)) {
yield return new ValidationResult(
$"Property {nameof(CanBeRenamed)} is not valid",
new [] { $"{nameof(CanBeRenamed)}" })
}
}
In case if you rename you property using refactoring tools, your validation will not be broken.
Everyone knows this
using (var db = new DatabaseEntites())
{
var row = db.SomeTable.SingleOrDefault(r => r.Id == 5)
}
I planned to create a static class with a static method like this
public static class SomeTableRepository
{
public static class GetSomeTableRow(DatabaseEntities db, int id)
{
return db.SomeTable.SingleOrDefault(r => r.Id == 5);
}
}
and the first code would then look like this
using (var db = new DatabaseEntites())
{
var row = SomeTableRepository.GetSomeTableRow(db, id);
}
If this would be a web app...would that kind of programming be ok...or could that kind of programming cause some trouble?...or is this perfectly good code :)
The code is technically acceptable, but why would you do it? It's creating an indirection without making the code substantively more concise. Thus you make your code harder for most people to understand. The benefit is your code is two characters shorter. That doesn't seem like a win to me.
Myself, I would use the standard LINQ operators unless I'm genuinely adding some real value.
As Kirk said, I think the only gain is minor readability. However, if you add this in front of your first parameter and make this an extension method, then you might gain some readability for potential readers of your code:
UPDATE
I also noticed that public static class GetSomeTableRow would not compile. I changed it to be more generic and less confusing for future readers (class to YourClassName)
public static class SomeTableRepository
{
public static YourClassName GetSomeTableRow(this DatabaseEntities db, int id)
{
return db.SomeTable.SingleOrDefault(r => r.Id == 5);
}
}
...
database.GetSomeTableRow(id);
Furthermore, you could rename this to make it read more like what it actually is:
database.GetOneRowFromSomeTableById(id);
Yes, it is lengthy, but the only reason to abstract such a simple method as SingleOrDefault would be to make the code even readable at a glance. The ById part is debatable since the parameter is named id (and it makes it seem redundant), however that only shows up while coding with intellisense. You could leave it out (or take it down to just By without Id...but that leaves too much for each implementer IMO)
database.GetOneRowFromSomeTable(id);
So insteed of writing:
if (obj.Collection == null)
obj.Collection = new Collection();
obj.Collection.Add(something);
I thought of writing:
obj.Collection = obj.Collection ?? new Collection;
obj.Collection.Add(something);
It kind of feels wrong, especially this part "obj.Collection = obj.Collection..."
What do you guys think ?
Regards,
If I had to choose between these two blocks of code, I would use the former. It's more readable and it's a common pattern. ?? is useful in scenarios where you need to default a value (e.g., DateTime date = nullableDateTimeInstance ?? defaultDate;).
But frankly, I'd try to not end up in situation where I want to add to collection and it's possible that the collection is null. Instead, I'd make sure that the collection is initialized in the constructor or whatever the case may be.
Do you mean:
if (obj.Collection == null)
{
obj.Collection = new Collection();
}
obj.Collection.Add(something);
If so, you can rewrite it as
(obj.Collection = (obj.Collection ?? new Collection())).Add(something);
The code will emit an unnecessary assignment (of obj.Collection to itself) if obj.Collection is not null, but other than that it is equivalent to the original.
Looks fine to me provided you don't use it in time critical sections. Anyway it's possible the compiler can optimise the assignment away, but I don't know if it would or not.
Perhaps it just feels wrong because the original code is such a common and simple pattern that it feels wrong to change it.
I'd say it also depends on what the setter of the Collection property does. Consider this:
public Collection Collection
{
get { return _collection; }
set
{
_collection = value;
Thread.Sleep( 1000 ); // or some expensive real work
}
}
In this case, the assignment obj.Collection = obj.Collection ?? new Collection() would be really costly.
However, if you need to create a collection "on demand", it's common to use a similar pattern in the property getter, like this:
public Collection Collection
{
get { return _collection ?? ( _collection = new Collection() ); }
}
In my business layer, I need many, many methods that follow the pattern:
public BusinessClass PropertyName
{
get
{
if (this.m_LocallyCachedValue == null)
{
if (this.Record == null)
{
this.m_LocallyCachedValue = new BusinessClass(
this.Database, this.PropertyId);
}
else
{
this.m_LocallyCachedValue = new BusinessClass(
this.Database, this.Record.ForeignKeyName);
}
}
return this.m_LocallyCachedValue;
}
}
I am still learning C#, and I'm trying to figure out the best way to write this pattern once and add methods to each business layer class that follow this pattern with the proper types and variable names substituted.
BusinessClass is a typename that must be substituted, and PropertyName, PropertyId, ForeignKeyName, and m_LocallyCachedValue are all variables that should be substituted for.
Are attributes usable here? Do I need reflection? How do I write the skeleton I provided in one place and then just write a line or two containing the substitution parameters and get the pattern to propagate itself?
EDIT: Modified my misleading title -- I am hoping to find a solution that doesn't involve code generation or copy/paste techniques, and rather to be able to write the skeleton of the code once in a base class in some form and have it be "instantiated" into lots of subclasses as the accessor for various properties.
EDIT: Here is my solution, as suggested but left unimplemented by the chosen answerer.
// I'll write many of these...
public BusinessClass PropertyName
{
get
{
return GetSingleRelation(ref this.m_LocallyCachedValue,
this.PropertyId, "ForeignKeyName");
}
}
// That all call this.
public TBusinessClass GetSingleRelation<TBusinessClass>(
ref TBusinessClass cachedField, int fieldId, string contextFieldName)
{
if (cachedField == null)
{
if (this.Record == null)
{
ConstructorInfo ci = typeof(TBusinessClass).GetConstructor(
new Type[] { this.Database.GetType(), typeof(int) });
cachedField = (TBusinessClass)ci.Invoke(
new object[] { this.Database, fieldId });
}
else
{
var obj = this.Record.GetType().GetProperty(objName).GetValue(
this.Record, null);
ConstructorInfo ci = typeof(TBusinessClass).GetConstructor(
new Type[] { this.Database.GetType(), obj.GetType()});
cachedField = (TBusinessClass)ci.Invoke(
new object[] { this.Database, obj });
}
}
return cachedField;
}
Check out CodeSmith. They have a free trial and it's not too expensive if you want to purchase it. I've used it and it's great for generating code based on databases (which is what I'm guessing you're doing). Once you have your template setup, you can regenerate the code at any time. You can have it read the property names right from the database schema or you can enter the values you want to use. I'm sure you could even get it to read the values from a file if you wanted to generate a whole batch of classes at once.
You could check out using T4 Templates. I am not quite sure which is "the" resource for T4, but I found a good article on it in VisualStudioMagazine.
It is free, has an easy to use syntax and is actually used by a lot of projects (e.g. Subsonic) for code generation, so you should be able to find some real-world scenarios.
You can code-gen using CodeSmith or MyGeneration or the like. You'd probably store a list of classes and properties somewhere and then pass that data to the code generator. You may want to investigate using pre-build events to re-gen those classes prior to compiling the solution.
Or, you could bake this functionality into a base class or helper method.
public BusinessClass MyProperty
{
get { return GetCached("MyProperty", "PropertyId", "FKName", "LocalValue"); }
}
I'll leave the body of GetCached() up to you, but it's basically the same as what you posted with the variables passed in as arguments.
If any of those values are the same for all properties in a class then you could of course pull them from instance variables, and only pass to GetCached() those things that vary on a per-property basis.
Bottom line: if there's a way to abstract the logic of what you're doing into a base method, so that using that logic becomes a one-liner, then that's probably the best way to go because it's easier to override when you have special cases. If you can't do that, code generation can do the grunt work for you, but you'll need to work out things like when do I re-gen, how do I regen, etc.