|
I was not aware that one is called an Object Initializer and the other is called a Collection initializer. Thank you for pointing that out. I will research that.
What prompted me to ask this question is that my code worked either way.
|
|
|
|
|
Just to add some clarification, since there seems to be so much consternation.
One of those is an explicit constructor call, MyClass(). The second is an initializer, which allows you to populate values as you see fit regardless of their "safety". It also requires a default constructor for the class, otherwise you're stuck calling the constructor then the initializer. This all means that if a constructor is defined with arguments, you can initialize in a safe way as defined by whoever created that class. For instance:
public class MyClass
{
public string Greeting { get; set; }
public bool IsGoodDayGreeting { get; set; }
public MyClass(){}
public MyClass(string greeting)
{
Greeting = greeting;
IsGoodDayGreeting = greeting.Equals("Good Morning") || greeting.Equals("Good Day");
}
}
Now that we've got the class, we have 3 ways to initialize it:
var greeting = new MyClass("Good Day");
var greeting3 = new MyClass { Greeting = "Good Morning" };
var greeting4 = new MyClass("Hello") { IsGoodDayGreeting = true };
As long as you bear the possible deviations in mind when breaking away from the constructor this is all fine and dandy, and a good dev will make sure that Object Initialization will not break an object's functionality, but if you rely on that without checking you are ultimately doomed to disappointment.
The last piece is constructor initialization. This only applies to items that implement IEnumerable, so it will work with Arrays, Lists, Dictionaries, etc.
var greetings = new List<MyClass>
{
new MyClass("Hello"),
new MyClass("Good Morning"),
greeting2,
greeting4
};
As expected, that results in a list populated with 2 new instances of MyClas and, assuming it's in scope with the above code, the previously defined greeting2 and greeting4.
Anyway, I hope this is what you needed.
"There are three kinds of lies: lies, damned lies and statistics."
- Benjamin Disraeli
|
|
|
|
|
Great answer! My class has no getters or setters and no constructor but I had forgotten that the compiler creates an empty constructor.
I was not aware also that obj() was called an object initializer and collection{} was called a collection initializer, so I was not finding answers online.
So now I understand why I can initialize the class with parenthesis - because of the empty constructor that's created by the compiler. I'm still kinda wondering why curly brackets worked too, though. This is just a collection of methods I'm using throughout my application.
|
|
|
|
|
That's not quite right.
var obj = new Thing();
var obj2 = new Thing { Name = "Thing" };
var obj3 = new Thing() { Name = "Thing" };
var objs = new List<Thing> { obj, obj2, obj3 };
All are valid C#. I personally favor constructors when I'm working with a class that I didn't write which takes parameters, less room for whoops.
"There are three kinds of lies: lies, damned lies and statistics."
- Benjamin Disraeli
|
|
|
|
|
I have an API that I am trying to use that uses XML for it's requests. Each of these objects have multiple different requests (Add, Modify, and Delete), along with different versions that may exclude some fields. Is there a way to utilize serialization with different schema to account for these differences? For example, using the following Customer object:
public class Customer
{
public int ID;
public string EditSequence;
public string Name;
public bool IsActive;
public int? ParentID;
} On a Delete request, I have to only supply the ID and the EditSequence fields. If I include the other fields, I get an error. For an Add I need to include all of them. Also, for null fields, they can not be included at all (i.e. no <parent> element). I don't think this is possible with regular XML serialization and I'll probably have to code this myself. If so, I was thinking of using custom attributes and reflection. Is there perhaps a better way to accomplish what I am trying?
|
|
|
|
|
Please clarify what you are doing: are you making calls to an API passing run-time field values, or, are you calling an API passing some pointer to a serialized xml file, or, to an in-memory xml stream ?
How does serialization come into play here ?
«While I complain of being able to see only a shadow of the past, I may be insensitive to reality as it is now, since I'm not at a stage of development where I'm capable of seeing it.» Claude Levi-Strauss (Tristes Tropiques, 1955)
|
|
|
|
|
The API that I am using takes an XML string. The XML string is based on what request I am trying to do. So, if I have an instance of a customer in my application that does not yet exist in the API software, I create an AddRq XML string, which has all of the fields for the customer:
<CustomerAddRq>
<CustomerAdd>
<Name>John Smith</Name>
<IsActive>1</IsActive>
...
</CustomerAdd>
<CustomerAddRq> Once I process this Add request, I get the ID associated with it, which I save in my custom object. If I then decide I want to update the customer record, I need to pass an slightly different XML string:
<CustomerModRq>
<CustomerMod>
<ID>456</ID>
<Name>John H. Smith</Name>
<IsActive>1</IsActive>
...
</CustomerMod>
</CustomerModRq> In my application, I still have just the one instance of this customer. Also, if I am wanting to delete this customer from the API software, I would pass this request:
<CustomerDelRq>
<CustomerDel>
<ID>456</ID>
</CustomerDel>
</CustomerDelRq> In each of these cases I have to be specific about which fields get included in the request or it will be rejected. If I were to include any other fields besides the ID in the delete request, the entire request is rejected and ignored. There's also some other factors based on the version of the API that might be in use. For example, they added a feature for tracking Currency in version 12, but if my customer is still using version 11, I need to never include the Currency field in my Add or Mod request or the entire request is rejected.
|
|
|
|
|
One way to do this would be to separate out your creation of the serialization from the Customer class, so you would have a DeleteCustomer class, for instance, that would accept an instance of your customer and which would return the appropriate XML. This helps to separate the concerns of your code.
This space for rent
|
|
|
|
|
Serialization has nothing to do with functionality. It is solely about data. So it doesn't matter how you modify/update/create that data.
hpjchobbes wrote: On a Delete request, I have to only supply the ID and the EditSequence fields
What you are referring to is generally about a 'difference'.
And it has nothing to do with the object itself.
The object represents a set of data and functionality associated with the data.
You are attempting to push functionality that involves a specific API and delivery of that data into the object itself. Bad idea.
What needs to happen is that the API layer (your code) needs to understand what it needs to deliver and then provide a way to do that. And not one that relies on the object to do it.
To provide a difference you MUST have two instances of the object. A before and an after. Then the API layer provides a way to either generally or specifically define the difference.
Be very careful in your design decision because a general approach ties one to the idea that ALL objects will be delivered using a difference. If there is even one exception then one must break the architecture to deal with it. Which is not the same an understanding that many objects, but not all, need to be handled with a difference.
One part of handling a difference also requires that one must be able to define the 'id'. That might not solely be one attribute. A general solution would require a way to recognize the specific attribute(s) that are the 'id'. That would either require metadata or hard coded by each object. One way, there ARE other ways, to provide the id is to require an interface on the the object that returns, as a string (generic solution) the id value.
|
|
|
|
|
Your question is too vague.
You say you "get an error" ... What "error"?
And "null" elements can be suppressed from the output xml using attributes; so this is not an issue (either).
"Transactions" typically employ a "transaction code" that identifies what fields are "required", optional or not applicable. Using a common template for all you transactions should not be an issue with the proper "codes" and logic in place.
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
The error is from the API. If I include a field in a request the entire request will be rejected. For example, in a Delete request I can ONLY pass the saved ID of this record. If I include any other information besides the ID (like the name of the customer) the entire request is rejected. If I include a blank <id> tag in an Add request it gets rejected instead of ignored. If I don't include the ID in a Modification request, the request gets rejected.
In this API, a Customer for example can be Added which has one XML Schema, if it already exists then I need to use the Mod XML schema which is slightly different. If I want to delete this Customer, then I have to use the Del XML Schema. All of the data for these schema are coming from my single customer instance.
|
|
|
|
|
When I deal with XML API's, I often just convert the XML to classes (using "Paste special" initialy); operate on the classes; and then serialize any "output" classess to strings (i.e. xml) for transmission, using the XmlSerializer.
Morteza Sahragard - 'Paste Special': a less well-known feature in Visual Studio
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
modified 28-Dec-17 12:34pm.
|
|
|
|
|
Can't seem to get past this. Everything I do is giving me an invalid cast exception.
I'm using GetOleDbSchemaTable ( OleDbSchemaGuid.Columns, ...) to return schema information on an Access table.
Columns that return value types are giving me problems. I'm not extremely experienced in C# so this is probably something basic.
The documentation says that the DATA_TYPE column in the resultset is a
UInt16 which I should be able to cast like this:
ushort DATA_TYPE = (ushort)row.Field<UInt16> ( "DATA_TYPE" ); but that gives me the same invalid cast exception. I can't even be sure that the cast that is causing the exception is ushort and UInt16 because I'm not understanding where to look.
|
|
|
|
|
If you don't know the "type", move whatever to an "object" or a "var" and then use reflection, debugging, intellisense, .GetType().ToString(), etc. to "discover" what type you are working with.
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
Thanks Gary. I actually wrote a generic method that I thought would take care of the casting issue, but now I'm getting an "unable to convert from type Object to type Long." I've posted it as a separate question because I'm probably not understanding what syntax to use.
|
|
|
|
|
Note that the generic method resolved the first problem I was having, which is that it was returning DBNull in situations for non-nullable types. I understand that the DB field is returned as an object and I understand that the object returned is not going to be implicitly converted to the C# types.
What I can't understand is the syntax I need to use in the generic method. I suspect it's the <t> part because that's where I'm getting "Unable to cast type Object to type long" exceptions
public T DBToType<T> ( T value )
{
if ( !Convert.IsDBNull ( value ) )
{
return ( T ) Convert.ChangeType ( value , typeof ( T ) );
}
else
{
return default ( T );
}
}
|
|
|
|
|
I'm working on a WPF app that accesses its data from a DAL class hitting SQL on a server. Pretty standard.
I want to make the calls to the DAL async. So I have:
public async Task<CompanyEntity> GetCompany(int id)
{
using (var db = new JayhawkDB())
{
CompanyEntity results = null;
try
{
var query = from x in db.Companies
where x.Id == id
select x;
var record = query.FirstOrDefault<Company>();
results = new CompanyEntity
{
Id = record.Id,
CreatedById = record.CreatedById,
CreatedDT = record.CreatedDt,
DeletedById = record.DeletedById.GetValueOrDefault(),
DeletedDT = record.DeletedDt.GetValueOrDefault(),
CompanyName = record.CompanyName,
Abbreviation = record.Abbreviation,
Notes = record.Notes
};
}
catch (Exception e)
{
throw;
}
return results;
}
}
I get a warning under the method name that says "The method lack await operators and will run synchronously..."
That message is correct. The really isn't anything here to await on. Therefore this will be a blocking call.
I want the ViewModel to call through the BL an into the DAL and have the VM await the call so the UI doesn't get blocked.
What the right way to do this?
Thanks
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
You only need the async modifier if you've got an await in the method. All this method needs to do is return a Task or some kind, which your method isn't doing. A dirty conversion of your code to returning a Task would be:
public Task<CompanyEntity> GetCompany(int id)
{
return Task.Factory.StartNew<CompanyEntity>(() =>
{
using (var db = new JayhawkDB())
{
CompanyEntity results = null;
var query = from x in db.Companies
where x.Id == id
select x;
var record = query.FirstOrDefault<Company>();
results = new CompanyEntity
{
Id = record.Id,
CreatedById = record.CreatedById,
CreatedDT = record.CreatedDt,
DeletedById = record.DeletedById.GetValueOrDefault(),
DeletedDT = record.DeletedDt.GetValueOrDefault(),
CompanyName = record.CompanyName,
Abbreviation = record.Abbreviation,
Notes = record.Notes
};
return results;
});
}
}
The caller await s this code, not the other way around.
Oh, and that try/catch block is pretty much useless if all you're going to do is catch all Exceptions and just re-throw them.
System.ItDidntWorkException: Something didn't work as expected.
C# - How to debug code[ ^].
Seriously, go read these articles.
Dave Kreskowiak
|
|
|
|
|
Ya know... I thought of that and then thought "Gee that doesn't look right"
Well duh
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
I need to know the key that is currently pressed in a C# WPF application, so:
List<Key> PressedKeys = new List<Key>();
private void Window_KeyDown(object sender, KeyEventArgs e)
{
if (!PressedKeys.Contains(e.Key))
{
PressedKeys.Add(e.Key);
txtKeysDown.Text = String.Join(", ", PressedKeys);
}
}
private void Window_KeyUp(object sender, KeyEventArgs e)
{
PressedKeys.Remove(e.Key);
txtKeysDown.Text = String.Join(", ", PressedKeys);
}
This works, sort of. However, it does not give me the raw input from the keyboard so when AltGr is pressed it canges from Key.RightAlt => Key.LeftCtrl + Key.RightAlt whitch is Windows interpretation according to this: AltGr key - Wikipedia[^]. I dont want this, as I want the user to be able to "bind" any key to a spesific action.
So I tried to use the user32.dll call:
[DllImport("user32.dll", EntryPoint = "GetKeyboardState", SetLastError = true)]
private static extern bool NativeGetKeyboardState([Out] byte[] keyStates);
private static bool GetKeyboardState(byte[] keyStates)
{
if (keyStates == null)
throw new ArgumentNullException("keyState");
if (keyStates.Length != 256)
throw new ArgumentException("The buffer must be 256 bytes long.", "keyState");
return NativeGetKeyboardState(keyStates);
}
private static byte[] GetKeyboardState()
{
byte[] keyStates = new byte[256];
if (!GetKeyboardState(keyStates))
throw new Win32Exception(Marshal.GetLastWin32Error());
return keyStates;
}
private static bool AnyKeyPressed()
{
byte[] keyState = GetKeyboardState();
return keyState.Skip(8).Any(state => (state & 0x80) != 0);
}
}
With the function:
bool MyIsKeyDown(Key key)
{
return (((byte)GetKeyboardState()[(int)key] & 0x80) & 0x80)>0;
}
and code implementation:
private void Window_KeyDown(object sender, KeyEventArgs e)
{
foreach (Key item in Enum.GetValues(typeof(Key)))
{
if (MyIsKeyDown(item))
{
if (!PressedKeys.Contains(e.Key))
{
PressedKeys.Add(e.Key);
txtKeysDown.Text = String.Join(", ", PressedKeys);
}
}
}
}
But still, windows insisted on giving me the replacement Key.RightAlt => Key.LeftCtrl + Key.RightAlt. So how do I get the key pressed on the actual keyboard?
|
|
|
|
|
|
I've been using the "Keyboard" class to get the state of my keys; apparently without any issues. e.g.
bool ok = ( Keyboard.IsKeyDown( Key.LeftShift ) || Keyboard.IsKeyDown( Key.RightShift ) );
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
That could work, but I also want it to react to a sequence of inputs like Visual Studio does. For instance, if you have selected parts of the code you can hold LeftCtrl + K, release the keys and press LeftCtrl + F, VS will format the code for you. Then KeyBoard.IsDown is not really usable.
The problem is that I need to know what happened on your keyboard before windows do changes to it.
|
|
|
|
|
"Keyboard" is a "class"; "IsDown" is only one method; I didn't say to use it; it was an example.
Anyway, what you're citing is a "sequence of key states" that translates into some operation; and has nothing to do with testing individual key states.
Your problem is determining / tracking intent once a key is pressed.
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
|