Saving data in a string - c#

Is it possible to store some kind of custom binary data in a string object?
For example, I have the string "Hello!", which represents a sequence of bytes.
Can I store an additional byte on that string that will be meaningful only to me?
For example, an extra byte that represents the string's length.
Is there a way to tell the .NET's decoder (which decodes these bytes) to ignore these custom bytes?

You really shouldn't go about it that way. How about creating a class that does what you want:
public class myString
{
public string stringValue;
public byte someSpecialByte;
public override string ToString()
{
return stringValue;
}
}
Then you can store whatever information you want in the class.
myString s = new myString();
s.stringValue = "Hello!"
s.someSpecialByte = 0;
Edit (In response to the constructor comment):
Add this to the class:
public myString(){} //default constructor
public myString(string sValue, byte specialByte)
{
stringValue = sValue;
someSpecialByte = specialByte;
}

Related

Empty array in string breaking deserialization

I have a string of JSON that I'm trying to convert into a list. There is an empty array value which is breaking the deserialization (have tried removing it manually or changing to a number and it works). Was thinking I could try to replace the [] in the string, but is there a better way to work around this?
public class Tax
{
public string Id;
public string Name;
public string PathOfTerm;
public string Children;
public string Level;
public string RawTerm;
}
var exString = "[{\"Id\":\"12345\",\"Name\":\"aName\",\"PathOfTerm\":\"aTerm\",\"Children\":[],\"Level\":0,\"RawTerm\":null}]";
JavaScriptSerializer ser = new JavaScriptSerializer();
var taxData = ser.Deserialize<List<Tax>>(exString);
The value is an array, but your field is a string. I suggest you make it an array (or list) of the appropriate type - we can't tell what that type would be from your JSON, but perhaps you want a string array?
I'd also suggest using properties instead of public fields.
(If you can move to Json.NET, I'd generally recommend that over JavaScriptSerializer, too...)

C# string format unknown size

Let's say I have the following string:
string postData = "state={2}&country={3}&geolocation={0}&city={1}";
And I have another list of strings. Its size could be in this case 4 at most.
I'm trying to create a method which replaces the numbers in my postData variable, depending on the list size. Something like the following method:
private string UnknownSizeStringFormat(string postData, params string[] stringsToReplace)
{
return string.format(postData, stringsToReplace);
}
The above method works as long as the list's size is 4. The thing is, on the first call, my list's size could be smaller than 4, so if it's 0 for example, I would like to replace each number inside the brackets with an empty string. My return value should be:
"state=&country=&geolocation=&city="
If its size is one, and the first member in the list is "21,27" my return string should be:
"state=&country=&geolocation=21,27&city="
And so on...
I could use a loop or a Regular Expression for this purpose but I've been wondering if there is a better way, a Linq solution perhaps? What I do know is how many numbers postData could have at most, which in my case is 4.
Again, I could do that with a loop or a Regular Expression, but I'm trying to make it as short as possible
Edit: The postData string could vary. That was just an example. Its size or content could be different
What I do know is how many numbers postData could have at most
Then how about this:
static string UnknownSizeStringFormat(string format, int maxArgs, params object[] args)
{
Array.Resize(ref args, maxArgs);
return string.Format(format, args);
}
so you can use:
string postData = "state={2}&country={3}&geolocation={0}&city={1}";
var result = UnknownSizeStringFormat(postData, 4);
You could use something like this:
private string UnknownSizeStringFormat(string postData, params string[] stringsToReplace)
{
string[] temp = { "", "", "", "" };
Array.ConstrainedCopy(stringsToReplace, 0, temp, 0, stringsToReplace.Length);
return string.format(postData, temp);
}
If you are allowed to write in C#6, then I would suggest you the following quick solution
Define a class that has as properties the parameters you refer to and ovveride the ToString method in a such a way to return the url you want.
public class CustomUrl
{
public string State {get;set;}
public string Country { get;set;}
public string Geolocation {get;set;}
public string City {get;set;}
public ovveride string ToString() =>
$"state={State}&country={Country}&geolocation={Geolocation}&city={City}";
}
you can use it as:
var customUrl = new CustomUrl
{
Geolocation = "21,27";
}
Then calling customUrl.ToString(), you would get:
"state=&country=&geolocation=21,27&city="
While creating another customer url as:
var customUrl = new CustomUrl();
and the calling customUrl.ToString() you would get:
"state=&country=&geolocation=&city="
If you are not allowed to write in C#, you have to modify a bit the class's definition, like below:
public class CustomUrl
{
public string State {get;set;}
public string Country { get;set;}
public string Geolocation {get;set;}
public string City {get;set;}
public ovveride string ToString()
{
retrun string.Format("state={0}&country={1}&geolocation={2}&city={3}",State,Country,Geolocation,City);
}
}
However, the best solution can be found at Named Formats Redux, the Henri formatter. If you implement this, you could call it as an extension method, like below:
var template = "state={state}&country={country}&geolocation={geo}&city={city}";
var customUrl = template.HenriFormat(new { geo = "21,72"});
The reason I say that this is the best solution is the fact that you would implement it once and you could use it anywhere, without have to implement a custom class for a case like the above.
I would start by adjusting your postData based on stringsToReplace.Length. You can use a switch/case method to control this. This is non-tested code, so please use with debug to verify.
string postData = "state={2}&country={3}&geolocation={0}&city={1}";
private string UnknownSizeStringFormat(string postData, params string[] stringsToReplace)
{
switch(stringsToReplace.Length){
case 0:
postData = "state={0}&country={0}&geolocation={0}&city={0}";
break;
case 1:
postData = "state={0}&country={0}&geolocation={1}&city={0}";
break;
case 2:
postData = "state={2}&country={0}&geolocation={1}&city={0}";
break;
case 3:
postData = "state={2}&country={3}&geolocation={1}&city={0}";
break;
case 4:
postData = "state={2}&country={3}&geolocation={1}&city={4}";
break;
return string.format(postData, String.Empty, stringsToReplace);
}
}

Formatted string as datatype

I have a format for certain Ids and I'd rather have a custom datatype for them rather than store them as a string.
How is this done in C#?
Is this a good idea in the first place?
An example below should explain what I mean:
Id format (D for digit, C for alphabet char): CCDDDD
public ItemId id { get; set; }
...
public class ItemId {
// somehow declare the format here
}
You could wrap a class around your string ID which takes a input string as constructor parameter. This way you can also put methods in your class to provide extra functionality etc, and always have the formatting in one place. Simple example:
public class ItemId
{
private string _id;
public string ID
{
get { return _value; }
set
{
//do some formatting here
_id= value;
}
}
public ItemId(string id)
{
ID = id
}
public override string ToString()
{
//do some extra formatting here if needed
return Value;
}
}
Because you can only manipulate the real ID through the public setter, you can have your formatting and validation logic in one single place. Hope this helps you a bit. I think it's a good idea because a class ItemId is more meaningful then just a string, and also a lot easier to extend or change functionality in the future.
For example you can check the input with regex, and throw your own exception if input does not match your format. That gives you meaningful information at runtime. Also you can add xml comment to the public setter, so if you or anyone uses it, it's clear what the ID should look like.
You can also do it by implementing your extensions, which I would prefer than overriding ToString method.
For Example
public static class Extension
{
public static string MyFormat(this string str)
{
//do sth with your string
return str;
}
}
And you can use this extension like
string abc = "";
abc.MyFormat();

JsonConvert.DeserializeObject throws an exception when attempting to deserialize byte[] to IEnumerable<byte>

The code below fails in deserialization with the following error.
Error converting value "AQID" to type 'System.Collections.Generic.IEnumerable`1[System.Byte]'
public class ByteArrayTest
{
public string SomeString { get; set; }
public IEnumerable<byte> ByteArray { get; set; }
}
using Newtonsoft.Json;
[TestClass]
public class UnitTest10
{
[TestMethod]
public void TestTheByteArraySerialization()
{
var test = new ByteArrayTest { ByteArray = new byte[] { 1, 2, 3 }, SomeString = "testing" };
var serializedData = JsonConvert.SerializeObject(test);
//This line belows fails with an error of can't convert to IEnumerable<byte>
var myByeArrayClass = JsonConvert.DeserializeObject<ByteArrayTest>(serializedData);
Assert.AreEqual(test.ByteArray, myByeArrayClass.ByteArray);
}
}
In my particular case I don't own the ByteArrayTest class, this is just a quick example of the issue. I'd like a solution that doesn't involve modifying the ByteArrayTest class. Ideally I'd pass something into one of the DeserializeObject<> overloads to get this to work, but I'm unsure of the best approach to resolve this exception
You can't expect JsonConvert to magically create an implementation for an interface.
You could use List<byte> or byte[] instead of IEnumerable<byte> if your architecture permits OR you can add a field to interface the Json serializer and hide your actual IEnumerable from it.
private IEnumberable<byte> myBytes = null;
[JsonProperty("BytesArray")]
public string JsonBytes{
get{
return String.Join("",myBytes.Select(b=>b.ToString("X2"))); // this may need tweaking, null checks etc
}
set{
byte[] bytes = Convert.FromBase64String(value);
myBytes = bytes;
}
[JsonIgnore]
public IEnumerable<byte> BytesArray{
get{ return myBytes;}
set{ myBytes = value;}
}
You could probably provide a converter to achieve the same thing but I'd say it's too much fiddling around without the need to.
For a list of several implementations on the StringToByteArray see this post, I copied the shortest implementation.

How does Console.WriteLine() know how to convert an object to a string

I am following the Preamble: what is a reference type? where it explains parameters passing as value or reference type. The first example has the following code:
using System;
using System.Text;
public class Example1
{
public static void Main (string[] args)
{
StringBuilder first = new StringBuilder();
StringBuilder second = first;
first.Append ("hello");
first = null;
Console.WriteLine (second);
}
}
And it does not provide the source code for the class (or struct) of StringBuilder, and I do not know how the Console.WriteLine(second) is able to return a string value just by using the identifier. Is it possible to return a value in the constructor?
I tried to write the class or struct by following (and it doesn't work):
struct StringBuilder
{
private string _myString;
public string StringBuilder
{
get { return _myString; }
set { _myString = value; }
}
public void Append(string str)
{
_myString = str;
}
}
Have a look a the documentation for Console.WriteLine(object value). It says this:
the ToString method of value is called to produce its string
representation, and the resulting string is written to the standard
output stream.
So (as others have written), if you want to print a string representation of your own class or struct, you should override the ToString() method.
StringBuilder is .net class in System.Text namespace.
Override ToString method for objects string representation.
public override string ToString()
{
return _myString;
}
Or print out your property:
Console.WriteLine (second.StringBuilder);
StringBuilder is a class, not a struct. C# is not like C++ in this respect: the two are in fact different. And Console.WriteLine(x) where x is an arbitrary class ends up as Console.WriteLine(x.ToString()).
What the code does is to call ToString on the StringBuilder instance. The code gets clearer if you explicitly call ToString instead of letting it be called implicitly:
Console.WriteLine(second.ToString());
You can override the ToString method in your own class. You should use classes, by the way, only use structs if you have a specific need for it. Structs are more complicated to implement correctly.
Example:
class Example {
public string Value { get; set; }
public Example(string value) {
Value = value;
}
public override string ToString() {
return Value;
}
}
Now the string value of your object will be its value:
Example ex = new Example("test");
Console.WriteLine(ex);

Categories