Identify optional elements in XSD in c# once imported with CodeDom - c#

I've analysed an XSD document inside which are some optional elements.
Within the produced C# code I find every int, decimal, datetime,... elements with an additional field xxxFieldSpecified. I understand this is for types not supporting null so the framework can know whether or not the element has been set and be used.
Is there however, a way to identify these fields when generating the class so I can automatically add a reference to this additional field when setting the field (using its property) instead of having to set the additional field all the time when setting the property, marking the property as set.
Also, when analysing the types inside a XmlShemaSet we know whether an element is an array (ArrayRank != 0). However, ArrayRank is always either 0 or 1 though sometimes the element is a multidimentional array, and ArrayRank should say 2 for instance...
Is tehre a way to identify multidimentional arrays produced using ArrayRank or any other property or field ?

For question 1 (optional elements) I found a way by when I find a property I check the list of fields looking for the propertyname+"FieldSpecified".
CodeMemberProperty m = (CodeMemberProperty)member;
if (m.HasSet)
{
// check if optional search for <name>FieldSpecified field
bool optional = false;
foreach (CodeTypeMember mtb in codeType.Members)
if (mtb is CodeMemberField)
if (optional = (0 == string.Compare(m.Name + "FieldSpecified", mtb.Name, true)))
break;
// if optional update setting flag when the property is set
if (optional)
{
// set ...FieldSpecified when setting the property
CodeAssignStatement cas = new CodeAssignStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), m.Name + "FieldSpecified"), new CodePrimitiveExpression(true));
m.SetStatements.Add(cas);
}
}
Probably not very smart but efficient.
If anybody has another way to do it...
Second question (multidimentional arrays) remains open.

Related

FirstOrDefault function default value [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have array of objects and I would like to find index of some specific object inside this array:
int ix = Array.IndexOf(products, products.Where(item => item != null && item.Id == "xxx").FirstOrDefault());
Item with Id="xxx" doesn't exists, but the ix result is 1.
So, I guess that default for int is 1. How can I know if 1 belongs to first item or default value? It would be nice if I can set default value to -1.
At the end I have done it with findIndex method, but would like to know how to do it with indexOf method.
So you have two parts of one problem. First, you want to find a product:
var product = products.FirstOrDefault(item => item != null && item.Id == "xxx");
And when that product is found, you want to find its index in the products collection:
int index = Array.IndexOf(products, product);
You're halfway there using FirstOrDefault(). If a product with Id "xxx" does not exist, product will be null. So you can check for that and skip IndexOf() for null:
if (product == null)
{
return -1;
}
else
{
return Array.IndexOf(products, product);
}
The fact that your current code returns 1, means that products[1] is null.
Per Microsoft:
Sometimes the value of default(TSource) is not the default value that you want to use if the collection contains no elements. Instead of checking the result for the unwanted default value and then changing it if necessary, you can use the DefaultIfEmpty(IEnumerable, TSource) method to specify the default value that you want to use if the collection is empty. Then, call First(IEnumerable) to obtain the first element.
However, I'm not so sure that's your issue. Your code isn't syntactically correct (you're missing a ')' somewhere), but it appears you're calling FirstOrDefault() after your Where(). This will either return an element or null. Since you said an item with id "xxx" doesn't exist, it's going to check for the index of null in your array. The default value for indexOf is (again, per Microsoft) "the lower bound of the array minus 1." This should return -1 (I'd hope) instead of 1.
Conclusion: take a better look at your code and see what's really going on. Break up this linq statement into two different parts.
var item = products.Where(item => item != null && item.Id == "xxx").FirstOrDefault();
int ix = Array.IndexOf(products, item);
Then step through your code to check the values of everything. I'm sure you will find your issue, and it won't be what you expected.
If you want to call FirstOrDefault on a struct but the default value is the same as a valid one, here's one thing you can do:
(I won't use your code as the missing parenthesis prevents from knowing what your goal is)
myCollection.Where(myCondition).Cast<int?>().FirstOrDefault();
This way, 0 would be the first correct value, and null would mean that there is no correct values.
First or default returns the first element (in this case, the first item found on the where conditions) OR, the default value.
This would return an OBJECT if conditions are met (the first object that mets the condition).
However, if conditions aren't met, it would return null (the default value of an OBJECT),
soo your code would be trying to find indexOf(products,null).. that would be an NullReferenceException.
The firstOrDefault is doing his job under the OBJECT type that is inside the array.
After this, the result is passed as parameter on the method indexOf.
"indexOf" will return the index of the first object on the "where" condition.
If not found, indexOf will return -1.
By the way, u're missing an parenthesis.

is Convert.toInt32(boolean) the only way in c# to do this?

I have some code in c# which needs to increment a number by 1 if a certain boolean value is true, but else it needs to say the same. The only method i've found using the Immediate window in VS 2012 is by + Convert.ToInt32(boolean).
Am I missing something obvious in here somewhere? I thought since a boolean is basically true (1) or false(0) (let's forget about FileNotFound), it would be easier to coerce a boolean to an Int value.
edit:
false is 0, not 1
edit2: my original edit got swallowed up. I'm currently doing a nullcheck on the number (the number is a nullable int field from a Dynamics CRM 2011 entity). Is it possible to keep that nullcheck?
I don't think that adding boolean flag to some value is very readable solution. Basically you want to increment (i.e. add 1) value if flag is true. So, simple if check will clearly describe your intent add do the job:
if (flag) value++;
UPDATE: According to your edit, you want to do two things:
Set default value to your nullable value
Increment value if some condition is true.
To make your code clear, I would not try to put both things in one line. Make your intent explicit:
value = value ?? 0; // 1
if (flag) // 2
value++;
The simple solution would be like so:
val += flag ? 1 : 0;
The fact is that a .NET boolean is simply a completely different type from integer (unlike in, say, C++, where it's a "renamed" integer). The fact, that it is actually implemented using an integer value, is implementation detail and not to be relied upon. In fact, you can do a lot of strange things when you mess with the actual value of the boolean (for example, using direct memory manipulation or overlapping structure fields) - the consistency goes away.
So, don't work with the "actual value of boolean". Simply expect the two possible values, true and false, and work with those.
You can still use the null-check and add the value according to the boolean, like this:
obj.Variable = (obj.Variable ?? 0) + (yourBoolean ? 1 : 0);
//obj is the instance of your object
//Variable is the nullable integer
//yourBoolean is the bool to check against
Object.variable is int variable OR Nullable? If Int varable it's default value is 0, and you can just write like this: Object.variable+=bool?1:0, else can use it: Object.variable=Object.variable??0+bool?1:0

Why does Enumerable.All return true for an empty sequence? [duplicate]

This question already has answers here:
Why does IQueryable.All() return true on an empty collection?
(11 answers)
Closed 7 years ago.
var strs = new Collection<string>();
bool b = strs.All(str => str == "ABC");
The code creates an empty collection of string, then tries to determine if all the elements in the collection are "ABC".
If you run it, b will be true.
But the collection does not even have any elements in it, let alone any elements that equal to "ABC".
Is this a bug, or is there a reasonable explanation?
It's certainly not a bug. It's behaving exactly as documented:
true if every element of the source sequence passes the test in the specified predicate, or if the sequence is empty; otherwise, false.
Now you can argue about whether or not it should work that way (it seems fine to me; every element of the sequence conforms to the predicate) but the very first thing to check before you ask whether something is a bug, is the documentation. (It's the first thing to check as soon as a method behaves in a way other than what you expected.)
All requires the predicate to be true for all elements of the sequence. This is explicitly stated in the documentation. It's also the only thing that makes sense if you think of All as being like a logical "and" between the predicate's results for each element. The true you're getting out for the empty sequence is the identity element of the "and" operation. Likewise, the false you get from Any for the empty sequence is the identity for logical "or".
If you think of All as "there are no elements in the sequence that are not", this might make more sense.
It is true, as nothing (no condition) makes it false.
The docs probably explain it. (Jon Skeet also mentioned something a few years back)
Same goes for Any (the opposite of All) returning false for empty sets.
Edit:
You can imagine All to be implemented semantically the same as:
foreach (var e in elems)
{
if (!cond(e))
return false;
}
return true; // no escape from loop
Most answers here seem to go along the lines of "because that's how is defined". But there is also a logical reason why is defined this way.
When defining a function, you want your function to be as general as possible, such that it can be applied to the largest possible number of cases. Say, for instance, that I want to define the Sum function, which returns the sum of all the numbers in a list. What should it return when the list is empty? If you'd return an arbitrary number x, you'd define the function as the:
Function that returns the sum of all numbers in the given list, or x if the list is empty.
But if x is zero, you can also define it as the
Function that returns x plus the given numbers.
Note that definition 2 implies definition 1, but 1 does not imply 2 when x is not zero, which by itself is enough reason to pick 2 over 1. But also note 2 is more elegant and, in its own right, more general than 1. Is like placing a spotlight farther away so that it lightens a larger area. A lot larger actually. I'm not a mathematician myself but I'm sure they'll find a ton of connections between definition 2 and other mathematical concepts, but not so many related to definition 1 when x is not zero.
In general, you can, and most likely want to return the identity element (the one that leaves the other operand unchanged) whenever you have a function that applies a binary operator over a set of elements and the set is empty. This is the same reason a Product function will return 1 when the list is empty (note that you could just replace "x plus" with "one times" in definition 2). And is the same reason All (which can be thought of as the repeated application of the logical AND operator) will return true when the list is empty (p && true is equivalent to p), and the same reason Any (the OR operator) will return false.
The method cycles through all elements until it finds one that does not satisfy the condition, or finds none that fail. If none fail, true is returned.
So, if there are no elements, true is returned (since there were none that failed)
Here is an extension that can do what OP wanted to do:
static bool All<T>(this IEnumerable<T> source, Func<T, bool> predicate, bool mustExist)
{
foreach (var e in source)
{
if (!predicate(e))
return false;
mustExist = false;
}
return !mustExist;
}
...and as others have pointed out already this is not a bug but well-documented intended behavior.
An alternative solution if one does not wish to write a new extension is:
strs.DefaultIfEmpty().All(str => str == "ABC");
PS: The above does not work if looking for the default value itself!
(Which for strings would be null.)
In such cases it becomes less elegant with something similar to:
strs.DefaultIfEmpty(string.Empty).All(str => str == null);
If you can enumerate more than once the easiest solution is:
strs.All(predicate) && strs.Any();
i.e simply add a check after that there actually were any element.
Keeping the implementation aside. Does it really matter if it is true? See if you have some code which iterates over the enumerable and executes some code. if All() is true then that code is still not going to run since the enumerable doesn't have any elements in it.
var hungryDogs = Enumerable.Empty<Dog>();
bool allAreHungry = hungryDogs.All(d=>d.Hungry);
if (allAreHungry)
foreach (Dog dog in hungryDogs)
dog.Feed(biscuits); <--- this line will not run anyway.

Storing, using custom logic in C#?

I am writing an app where I will give a set of tests/checks to the user through an UI such as:
LayerCount
ActiveLayerType
EffectCount
ActiveEffectType
CurrentTool
HasSelection
HasAlpha
etc
where the user is able to use them to define a custom logic tree such as:
if (LayerCount > 1)
{
if (ActiveLayerType == LayerType.Blend)
{
// #1
}
else if (ActiveEffectType == EffectType.GaussianBlur)
{
// #2
}
}
else if (CurrentTool == Tools.QuickSelect)
{
if (HasSelection)
{
// #3
}
}
Basically I am trying to define some sort of value that will return the Current Level in his custom logic in some way (let's say 1, 2, 3, and so on). Because I need to have the actions of the user interpreted differently based on the Current Level in his logic.
You could basically say that I am trying to hash a set of values based on the Current Level. But the problem is, I don't know how to get the current level to store it as a hash key. If I did, I could write something like:
var currentActionSet = ActionSetTable [GetCurrentLevel()]
and I would get a set of actions the user can perform based on the current level.
Although it would be more desirable to have these levels have fixed values instead of values starting from 1 to n, based on how they are ordered. So (ActiveEffectType == EffectType.GaussianBlur)'s branch would always return a fixed value no matter where it's in the logic tree.
So to sum up, the problems are:
How to define a current level value, preferrably fixed?
If using this current level value as key is the best approach, or if there is a better way of doing this?
Perhaps you can use bitflags and OR them together to make your hashcode?
int hash = ActiveLayerType | ActiveEffectType | CurrentTool
Then at some later point you can AND a perticular flag out again:
if( hash & LayerType.Blend == LayerType.Blend ) { ... } //will be true if the LayerType.Blend has previously been OR:ed into the hash variable
You can OR together enums of diffrent types too if you cast them to ints first, make sure that the enum bit values doesnt clash though.
This approach may or may not be practical for you application, but its something to consider :) more info here: http://msdn.microsoft.com/en-us/library/cc138362.aspx

Why isn't this DirectoryInfo comparison working? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to check whether 2 DirectoryInfo objects are pointing to the same directory?
var dirUserSelected = new DirectoryInfo(Path.GetDirectoryName("SOME PATH"));
var dirWorkingFolder = new DirectoryInfo(Path.GetDirectoryName("SAME PATH AS ABOVE"));
if (dirUserSelected == dirWorkingFolder)
{
//this is skipped
}
if (dirUserSelected.Equals(dirWorkingFolder))
{
//this is skipped
}
Whilst debugging, I can examine the values in each and they ARE equal. So i'm guessing this is another byval byref misunderstanding... Please someone, how do I compare these two things?
I believe you want to do this :
var dirUserSelected = new DirectoryInfo(Path.GetDirectoryName(#"c:\some\path\"));
var dirWorkingFolder = new DirectoryInfo(Path.GetDirectoryName(#"c:\Some\PATH"));
if (dirUserSelected.FullName == dirWorkingFolder.FullName )
{ // this will be skipped,
// since the first string contains an ending "\" and the other doesn't
// and the casing in the second differs from the first
}
// to be sure all things are equal;
// either build string like this (or strip last char if its a separator)
// and compare without considering casing (or ToLower when constructing)
var strA = Path.Combine(dirUserSelected.Parent, dirUserSelected.Name);
var strB = Path.Combine(dirWorkingFolder.Parent, dirWorkingFolder.Name);
if (strA.Equals(strB, StringComparison.CurrentCultureIgnoreCase)
{ //this will not be skipped
}
............
In you example you are comparing 2 different objects thats why they are not equal. I believe you need to compare Paths so use the code above.
I did a Google Search for "DirectoryInfo equality" and found several great results, including one on StackOverflow (How to check whether 2 DirectoryInfo objects are pointing to the same directory?)
If two Directory.FullNames match, then you know they are the same, but if they don't match, you still don't know much. There are short names and links and junctions and many other reasons two different strings could refer to the same location on disk.
If you count on knowing for sure that two strings aren't the same location, and security is at stake, you're likely creating a security bug. Tread carefully.
As Jaroslav Jandek says (sorry I can't comment, not enough reputation)
Because it compares those two
instances, not their value (two
references).
And actually it's the same for tons of other cases! For ex
IPAddress ip1 = IPAddress.Parse("192.168.0.1");
IPAddress ip2 = IPAddress.Parse("192.168.0.1");
Both IP addresses represent the same address, but you have two distinct instances of the IPAddress class. So of course "ip1 == ip2" and "ip1.Equals(ip2)" are both false, because they don't point to the same object.
Now if you check "ip1.Address == ip2.Address" the result will be true as IPAddress.Address is a "long", so you're comparing 2 value types. Note that "ip1.ToString() == ip2.ToString()" will also be true even if a string is a reference type not a value type (but strings are really specials).
So indeed in your case you want to compare the FullName property (it's a string so no problem).
You say
Is it only by using the properties, i.e. the .FullName property that you are comparing value rather than instance?
Actually it has more to do with whether the property is a value type or a reference type. Also when comparing reference types, in most cases the comparison will be whether or not they point to the same object, but it's possible to override methods or create operators so that the comparison is done on the content of the objects (again just like Jaroslav Jandek already pointed out).
HTH
Because it compares those two instances, not their value (two references).

Categories

Resources