Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
I'm maintaining a codebase and I've found two extension methods, dealing with checking the structural equality of objects, which I do not like at all (one invokes the other):
public static bool IsObjectEqual<T>(this T obj, T obj2)
{
foreach (var pi in obj.GetType().GetProperties())
{
var enumerable1 = pi.GetValue(obj, null) as IEnumerable;
var enumerable2 = pi.GetValue(obj2, null) as IEnumerable;
if (enumerable1 != null)
{
foreach (var item in enumerable1)
{
if (enumerable2 == null || !((object[])enumerable2).Contains(item))
{
return false;
}
}
}
else if (!IsPropertyInfoValueEqual(pi, obj, obj2))
{
return false;
}
}
return true;
}
private static bool IsPropertyInfoValueEqual<T>(PropertyInfo pi, T obj, T obj2)
{
var val = pi.GetValue(obj, null);
var val2 = pi.GetValue(obj2, null);
if (val != null && val2 != null)
{
return val.Equals(val2);
}
return (val == null && val2 == null);
}
The problem is, I'm having trouble coming up with a scenario where I think they will fail, or cause problems. I know it in my waters that they are wrong, I just can't put my finger on it.
I've always used IEquateable<T> when implementing equality checking, so the absence of any of the framework classes/Interfaces which deal with equality is one thing which invokes my spidey senses. I realise this method is trying to be a generalised, reflection-based approach, but it makes me nervous (as mentioned).
Can anyone see a legitimate problem with these methods?
Edit
Big legitimate problem with the methods. The cast to object[] results in an InvalidCastException.
There could be others, but I see two main problems with this code:
Reflection is expensive. Really expensive. To use it on such a large scale for something as simple as equality checking is just a bad idea. The code doesn't even cache the object graph so its having to do the full reflection every time. Under fairly common scenarios I can see this method being a performance bottleneck.
If members are IEnumerable, the code won't work as expected. Everything else is compared with reflection, but the collections are compared using Contains. This will do simple reference equality (for reference types at least) and doesn't reuse the reflective method. This would likely lead to undesirable results for the users of this method.
Implementing IEquatable and friends is a much faster, and safer, approach. The implementer gets to explicitly decide how the comparison works, and you don't need any reflection.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
Found the following code in one open source project, and I am amazed how original coder used local and static local functions in here:
public static Win32Error CallMethodWithTypedBuf<TOut, TSize>(SizeFunc<TSize> getSize, PtrFunc<TSize> method, out TOut result, Func<IntPtr, TSize, TOut> outConverter = null, Win32Error? bufErr = null) where TSize : struct, IConvertible
{
TSize sz = default;
result = default;
var err = (getSize ?? GetSize)(ref sz);
if (err.Failed && (bufErr == null || bufErr.Value != err) && !buffErrs.Contains(err)) return err;
using (var buf = new SafeHGlobalHandle(sz.ToInt32(null)))
{
err = method(buf.DangerousGetHandle(), ref sz);
if (err.Succeeded)
result = (outConverter ?? Conv)(buf.DangerousGetHandle(), sz);
return err;
}
Win32Error GetSize(ref TSize sz1) => method(IntPtr.Zero, ref sz1);
static TOut Conv(IntPtr p, TSize s) => p == IntPtr.Zero ? default : p.Convert<TOut>(Convert.ToUInt32(s));
}
So I've rewritten to something that would actually have logic in one place, and would work even in older compilers (As it would be written 10 years ago). To realize that following code is actually less in size, consumes less call stack, and could be better optimized by if-branch prediction:
public static Win32Error CallMethodWithTypedBuf<TOut, TSize>(SizeFunc<TSize> getSize, PtrFunc<TSize> method, out TOut result, Func<IntPtr, TSize, TOut> outConverter = null, Win32Error? bufErr = null) where TSize : struct, IConvertible
{
TSize sz = default;
result = default;
var err = (null != getSize ? getSize(ref sz) : method(IntPtr.Zero, ref sz));
if (err.Failed && (bufErr == null || bufErr.Value != err) && !buffErrs.Contains(err)) return err;
using (var buf = new SafeHGlobalHandle(sz.ToInt32(null)))
{
err = method(buf.DangerousGetHandle(), ref sz);
if (err.Succeeded)
{
IntPtr p = buf.DangerousGetHandle();
result = (null != outConverter) ? outConverter(p, sz) : (p == IntPtr.Zero ? default : p.Convert<TOut>(Convert.ToUInt32(sz)));
}
return err;
}
}
So I'am more than little confused why would anyone use local and static functions, as original coder did use. At this point I think people are angry and do not know what to do with themselfs, and started making mess at global scale. Please tell me that I am wrong, and that we all should use local and static local functions immediately all over our codes?
I think it's pretty clear from the way C# is developed that readability/ease of use is one of the core pillars for the language. Majority of the new features don't really provide anything truly new, besides giving you an option to write things differently, hopefully more readable/easier.
Almost always you are able to pick something written with a new feature and rewrite it without using it. It doesn't make the new feature invalid.
From design notes related to Local Functions, the intention is stated:
https://github.com/dotnet/roslyn/issues/3911
We agree that the scenario is useful. You want a helper function. You
are only using it from within a single function, and it likely uses
variables and type parameters that are in scope in that containing
function. On the other hand, unlike a lambda you don't need it as a
first class object, so you don't care to give it a delegate type and
allocate an actual delegate object. Also you may want it to be
recursive or generic, or to implement it as an iterator.
In your given example, I find the original code more readable.
The support for older compilers doesn't matter, if my project targets a new compiler, why would I care about old ones? If I do, where is the end of it? C#7? C#6? 4?
Performance is secondary to readability/maintainability of the code, only when something proves to be a bottleneck for you, you start optimizing it.
So having the options is good.
More advantages to local functions come in when you compare it versus a lambda function, there's a great answer here:
Local function vs Lambda C# 7.0
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I have an entity and I can have InvoiceLine on top of that, then you can credit that invoice line infinite no of times. but only main InvoiceLine have reference to original entity.
I am using recursion to get the original entity , but the code is not that readable
private static PermanentPlacement PopulatePermanentPlacement(InvoiceLine invoiceLine)
{
PermanentPlacement permanentPlacement;
var creditReissue = invoiceLine.CreditReissue;
do
{
permanentPlacement = creditReissue.InvoiceLine.PermanentPlacement;
if (permanentPlacement == null)
{
creditReissue = creditReissue.InvoiceLine.CreditReissue;
}
} while(permanentPlacement == null);
return permanentPlacement;
}
Is there any way I can make this more readable and simplify ?
I think the answer by René Vogt shows the best way to simplify this code. But there are others. For example, consider moving the loop to a helper function:
static IEnumerable<Reissue> CreditReissues(Reissue original)
{
var current = original;
while(true)
{
yield return current;
current = current.InvoiceLine.CreditReissue;
}
}
And now you don't ever need to write a loop again in order to use an infinite sequence of credit reissues:
private static PermanentPlacement PopulatePermanentPlacement(
InvoiceLine invoiceLine)
{
return CreditReissues(invoiceLine.CreditReissue)
.Select(cr => cr.InvoiceLine.PermanentPlacement)
.First(pp => pp != null);
}
That is: take the infinite sequence of credit reissues, turn it into an infinite sequence of permanent placements, and return the first non-null one in the sequence.
Notice how by changing the loop into a sequence, we can now describe the operations we want to perform on the level of sequences and not on the level of statements and variables.
Incidentally, you say -- twice -- that you are using recursion in the original code, but you are not. A recursive solution would look like this:
private static PermanentPlacement PopulatePermanentPlacement(
InvoiceLine invoiceLine)
{
return invoiceLine.PermanentPlacement ??
PopulatePermanentPlacement(
invoiceLine.CreditReissue.InvoiceLine);
}
You should not use a recursive solution for a potentially unbounded loop because C# is not guaranteed to be tail recursive, and therefore can blow the stack.
I would shorten the code to:
private static PermanentPlacement PopulatePermanentPlacement(InvoiceLine invoiceLine)
{
var creditReissue = invoiceLine.CreditReissue;
while(creditReissue.InvoiceLine.PermanentPlacement == null)
creditReissue = creditReissue.InvoiceLine.CreditReissue;
return creditReissue.InvoiceLine.PermanentPlacement;
}
This does the same as your code, except that it accesses PermantPlacement of the final InvoiceLine an extra time. So if this property getter does more than just returning a value, this modification may not be valid.
Your code seems pretty clear and readable to me. René Vogt's answer is about as short as you could make it without changing the logic but I have a gut feeling that what you really want might be this:
private static PermanentPlacement PopulatePermanentPlacement(InvoiceLine invoiceLine)
{
var creditReissue = invoiceLine.CreditReissue;
while (creditReissue.InvoiceLine.CreditReissue != null)
{
// Get the last credit reissue
creditReissue = creditReissue.InvoiceLine.CreditReissue;
}
return creditReissue.InvoiceLine.PermanentPlacement;
}
It does change the logic a bit, please validate that it is equivalent.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I've been coming across not equal != or !condition in conditional statements ever since I started programming. Maybe it's because my brain is pre-conditioned in the English language to overthink multiple negation. But I have been wondering, is there a common development community accepted practice when it comes to evaluating for true in conditional statements? Or rather, the way I see it sometimes: evaluating for not false.
Maybe there are exceptions where != cannot be completely unavoidable?
For Example:
This might be a very simple and trivial, but is this preferred
string myStringVar = "dogs";
if (myStringVar != "dogs") //In my mind, "False this is not true"
{
//code
}
else if (myStringVar != cats) //In my mind, "True this is false"
{
//code
}
Or is this preferable
if (myStringVar == "dogs")
{
//"True"
}
else if (myStringVar == "cats")
{
//"False"
}
Then there's
bool MyBoolMethod()
{
return false;
}
if (!MyBoolMethod()) // True this method does not return true
{
//code
}
This is a very trivial and simplified example, I just want to know how to write readable, maintainable code. Does anyone else have a somewhat difficult time reading conditionals like this or is it just me?
"None of the above."
Since you're using strings, the assumption is that myStringVar can be anything. If I say:
string myStringVar = "Aardvark";
Then your first example, it will run the myStringVar != "dogs" section of code; In the second example, neither will be executed. So they're not equivalent pieces of code.
The only way they would be equivalent is if you were using Enums (in which case I would suggest using a case statement).
In your third example, it would depend on what MyBoolMethod() was named, and how easy it was to understand by a future coder. To use an example,
bool isDog()
{
return false;
}
is is easy to understand. The question then becomes is
if(!isDog()) ...
more clear than
if(isNotDog()) ...
I would argue that the first is more clear than the second. There are other situations, however, where that is not the case.
Equality and inequality are just something one needs to get comfortable with and choose in context. If the logical problem requires looking to test against equality use equality if it is looking to disqualify use inequality.
The readability and maintainability can be reinforced through good design as you started to allude to with your mybool method.
Exmaple
public class Animal
{
public static Enum AnimalType
{
Dog,
Cat
}
private _animalType;
public Animal(Enum AnimalType type)
{
AnimalType = _animalType;
}
public bool isOfType(Enum AnimalType type)
{
return _animalType == type ? true : false;
}
}
public someothermethod()
{
//doing inclusion
If(MyAnmialObject.isOfType(Animal.AnimalType.Dog))
{
//if type matches
}
//Doing exclusion
If(!MyAnmialObject.isOfType(Animal.AnimalType.Dog))
{
//if type does not match
}
}
You still have to get used to inequality but you know it is checking for isOfType and the named type.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
When writting codes, using if by following way
int something = 5;
bool possible = false;
if( something>0 && !possible){
doSomething();
}
and
int something = 5;
bool possible = false;
bool condition1 = something > 0;
bool condition2 = !possible;
if( condition1 && condition2){
doSomething();
}
Which is more readable?
Which is more effective?
I assume 2nd is better when case like
if( Something > (SomeOtherThing + SomeSomeThing) && !Something.Something.Possible)
I know this doesn't directly concern with c# but want to know especially in c#!
There is no hard and fast rule, but quite often the code can be much more readable if you extract to speaking variable names or method calls. In the following example the condition is absolutely clear.
bool UserIsAdmin() { ... }
bool UserOwnsItem() { ... }
bool UserMayAccessItem {
return UserIsAdmin() || UserOwnsItem();
}
// ..
if (UserMayAccessItem()) {
// do something here
}
On the other hand there certainly may be simple cases where adding variables does not increase readability.
It basically is a matter of style and preference. Just keep in mind that the code should be easily readable and speak for itself.
The first option is preferable, not only because of shortcut evaluation, but also for maintainability.
I guarantee you that you or someone else will eventually change the conditions, without bothering to adapt the variable names, too, for example.
It is non-effective.
When condition1 is false, it is not required to calculate condition2 in your example. Sometimes this calculation eats resources (request to DB for example). In this case 2nd option is non-effective.
However it is readable, particularly when you name condition variables in more convenient way, for example:
bool somethingIsPositive = somithing > 0;
bool itIsImpossible = !possible;
if(somethingIsPositive && itIsImpossible)
...
Also you can leverage Lazy class (if you use C#) to not claculate condition2 all the time (even when condition1 is false), so this is really more readable and hasn't performance problems (when condition2 takes time to calculate, not in your case :) ):
int something = GetNumber();
bool possible = GetPossibility();
var somethingIsPositive = new Lazy<bool>(() => something > 0);
var itIsImpossible = new Lazy<bool>(() => !possible);
if( somethingIsPositive.Value && itIsImpossible.Value){
doSomething();
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I am making a sort of statistical software that firstly needs to 'detect' the datatype of an array.
Firstly, X[,] is an array of sometype, can be all strings, all double, all ints or a combination of all.
Now, for every column X[] I need to know the datatype. Like:
If everything is 0 or 1, then Boolean (or binomial)
elseIf everything is integer, then integer
elseIf everything is double, then double
else: String
I need something like this in C#.
So it seems what you're trying to do here is find the "lowest common denominator" of types here. The most derived type that all of the items in the collection "are".
We'll start out with this helper method to get the entire type hierarchy of an object (including itself):
public static IEnumerable<Type> BaseClassHierarchy(object obj)
{
Type current = obj.GetType();
do
{
yield return current;
current = current.BaseType;
} while (current != null);
}
Now we can take a sequence of objects, map each to its hierarchy, intersect all of those sequences with each other, and then the first item of that result is the most derived type that is common to all of the other objects:
public static Type MostDerivedCommonType(IEnumerable<object> objects)
{
return objects.Select(o => BaseClassHierarchy(o))
.Aggregate((a,b)=> a.Intersect(b))
.First();
}
One simple idea is you can try to cast/parse as the different types and if that fails, move on to the next type. A very brief example of this is:
foreach (var element in myArray) {
double parsedDouble; int parsedInt;
var defaultValue = element.ToString();
if (Double.TryParse(defaultValue, out parsedDouble)) {
// you have something that can be used as a double (the value is in "parsedDouble")
} else if (Int32.TryParse(defaultValue, out parsedInt)){
// you have something that can be used as an integer (the value is in "parsedInt")
} else {
// you have something that can be used as an string (the value is in "defaultValue")
}
}
I believe that should probably get you started. Good luck!
Note
As other's have said - it is better to use strong types in C#. In most cases you can probably select a single type and use that rather than performing the checks above.