How to Implicitly Convert an Enumerable of a type with Implicit Conversion Operators in C# 4.0 - c#-4.0

Given:
public struct Id
{
readonly int m_id;
public Id(int id)
{ m_id = id; }
public static implicit operator int(Id id)
{ return id.m_id; }
public static implicit operator Id(int id)
{ return new Id(id); }
}
Can you implicitly convert an
IEnumerable<int>
to
IEnumerable<Id>
and vice versa. In some way. Note that
var ids = new int[]{ 1, 2 };
ids.Cast<Id>();
does not appear to work and covariance does not appear to be working in this case, either. Of course, doing a select will work i.e.:
ids.Select(id => new Id(id));
But I am looking for something that would make this work implicitly, so writing:
IEnumerable<Id> ids = new int[]{ 1, 2 };
And yes, I know this can be written as:
IEnumerable<Id> ids = new Id[]{ 1, 2 };
But the issue is in cases where the enumerable of ints comes from a different source, such as a file for example.
I am sorry if there already is an answer for this, but I could not find it.

According to this answer what you want is not possible. But you can get close by not implicitly casting your id but your collection. Like this :
public class Ids : List<int>
{
public static implicit operator Ids(int[] intArray)
{
var result = new Ids();
result.AddRange(intArray);
return result;
}
}
then this is possible :
Ids t = new [] { 3,4 };

What's wrong with:
IEnumerable<int> data = GetDataFromSource();
IEnumerable<Id> ids = data.select(id => new Id(id));

Related

How to override "="

I was looking into Haxe abstracts and was very interested in building an abstract that would wrap a class and unify it to, in my case, an Int.
#:forward()
abstract Abs(Op)
{
public inline function new(value:Int = 0, name:String = "unnamed" )
{
this = new Op();
this.value = value;
this.name = name;
}
#:to
private inline function toInt():Int
{
return this.value;
}
}
class Op
{
public var value:Int = 0;
public var name:String = "no name";
public function new()
{
}
}
The problem I ran in to is when defining a #:from method - it has to be static and can take only one parameter - a new value. So whenever I set the abstract's instance value from the #:from method I will have to create a new instance of the abstract, thus resetting all the variables.
Basically what I'm talking about is this:
var a = new Abs(5, "my abs"); // value is 5; name is "my abs"
a = 100; // value is 100; name is reset to "unnamed" but I want it to be preserved
As much as I could find out we cannot overload the = operator in abstracts other than through implicit casting with a #:from method and I haven't found a way to really achieve this with macros.
If you have any ideas on how this can be done, please provide a minimalist example.
It depends what you want to do, but if you use this:
var a = new Abs(5, "my abs");
var myInt:Int = a;
It will use the abstract Abs.toInt function.
#:to
private inline function toInt():Int
{
return this.value;
}
The other way around also works:
var million = 1000000;
var myAbs:Abs = million;
It will use the static Abs.fromInt function.
#:from
static inline function fromInt(value:Int)
{
return new Abs(value, "what");
}
This is because it uses the implicit cast. http://haxe.org/manual/types-abstract-implicit-casts.html
Try it yourself: http://try.haxe.org/#Ae1a8
Is that what you are looking for?

How can I clone an Object (deep copy) in Dart?

Is there a Language supported way to make a full (deep) copy of an Object in Dart?
If multiple options exist, what are their differences?
Darts built-in collections use a named constructor called "from" to accomplish this. See this post: Clone a List, Map or Set in Dart
Map mapA = {
'foo': 'bar'
};
Map mapB = new Map.from(mapA);
No as far as open issues seems to suggest:
https://github.com/dart-lang/sdk/issues/3367
And specifically:
... Objects have identity, and you can only pass around references to them. There is no implicit copying.
Late to the party, but I recently faced this problem and had to do something along the lines of :-
class RandomObject {
RandomObject(this.x, this.y);
RandomObject.clone(RandomObject randomObject): this(randomObject.x, randomObject.y);
int x;
int y;
}
Then, you can just call copy with the original, like so:
final RandomObject original = RandomObject(1, 2);
final RandomObject copy = RandomObject.clone(original);
I guess for not-too-complex objects, you could use the convert library:
import 'dart:convert';
and then use the JSON encode/decode functionality
Map clonedObject = JSON.decode(JSON.encode(object));
If you're using a custom class as a value in the object to clone, the class either needs to implement a toJson() method or you have to provide a toEncodable function for the JSON.encode method and a reviver method for the decode call.
Unfortunately no language support. What I did is to create an abstract class called Copyable which I can implement in the classes I want to be able to copy:
abstract class Copyable<T> {
T copy();
T copyWith();
}
I can then use this as follows, e.g. for a Location object:
class Location implements Copyable<Location> {
Location({
required this.longitude,
required this.latitude,
required this.timestamp,
});
final double longitude;
final double latitude;
final DateTime timestamp;
#override
Location copy() => Location(
longitude: longitude,
latitude: latitude,
timestamp: timestamp,
);
#override
Location copyWith({
double? longitude,
double? latitude,
DateTime? timestamp,
}) =>
Location(
longitude: longitude ?? this.longitude,
latitude: latitude ?? this.latitude,
timestamp: timestamp ?? this.timestamp,
);
}
To copy an object without reference, the solution I found was similar to the one posted here, however if the object contains MAP or LIST you have to do it this way:
class Item {
int id;
String nome;
String email;
bool logado;
Map mapa;
List lista;
Item({this.id, this.nome, this.email, this.logado, this.mapa, this.lista});
Item copyWith({ int id, String nome, String email, bool logado, Map mapa, List lista }) {
return Item(
id: id ?? this.id,
nome: nome ?? this.nome,
email: email ?? this.email,
logado: logado ?? this.logado,
mapa: mapa ?? Map.from(this.mapa ?? {}),
lista: lista ?? List.from(this.lista ?? []),
);
}
}
Item item1 = Item(
id: 1,
nome: 'João Silva',
email: 'joaosilva#gmail.com',
logado: true,
mapa: {
'chave1': 'valor1',
'chave2': 'valor2',
},
lista: ['1', '2'],
);
// -----------------
// copy and change data
Item item2 = item1.copyWith(
id: 2,
nome: 'Pedro de Nobrega',
lista: ['4', '5', '6', '7', '8']
);
// -----------------
// copy and not change data
Item item3 = item1.copyWith();
// -----------------
// copy and change a specific key of Map or List
Item item4 = item1.copyWith();
item4.mapa['chave2'] = 'valor2New';
See an example on dartpad
https://dartpad.dev/f114ef18700a41a3aa04a4837c13c70e
With reference to #Phill Wiggins's answer, here is an example with .from constructor and named parameters:
class SomeObject{
String parameter1;
String parameter2;
// Normal Constructor
SomeObject({
this.parameter1,
this.parameter2,
});
// .from Constructor for copying
factory SomeObject.from(SomeObject objectA){
return SomeObject(
parameter1: objectA.parameter1,
parameter2: objectA.parameter2,
);
}
}
Then, do this where you want to copy:
SomeObject a = SomeObject(parameter1: "param1", parameter2: "param2");
SomeObject copyOfA = SomeObject.from(a);
Let's say you a have class
Class DailyInfo
{
String xxx;
}
Make a new clone of the class object dailyInfo by
DailyInfo newDailyInfo = new DailyInfo.fromJson(dailyInfo.toJson());
For this to work your class must have implemented
factory DailyInfo.fromJson(Map<String, dynamic> json) => _$DailyInfoFromJson(json);
Map<String, dynamic> toJson() => _$DailyInfoToJson(this);
which can be done by making class serializable using
#JsonSerializable(fieldRename: FieldRename.snake, includeIfNull: false)
Class DailyInfo{
String xxx;
}
It only works for object types that can be represented by JSON.
ClassName newObj = ClassName.fromMap(obj.toMap());
or
ClassName newObj = ClassName.fromJson(obj.toJson());
Trying using a Copyable interface provided by Dart.
there is an easier way for this issue
just use ... operator
for example, clone a Map
Map p = {'name' : 'parsa','age' : 27};
Map n = {...p};
also, you can do this for class properties.
in my case, I was needed to clone a listed property of a class.
So:
class P1 {
List<String> names = [some data];
}
/// codes
P1 p = P1();
List<String> clonedList = [...p.names]
// now clonedList is an unreferenced type
There is no built-in way of deep cloning an object - you have to provide the method for it yourself.
I often have a need to encode/decode my classes from JSON, so I usually provide MyClass fromMap(Map) and Map<String, dynamic> toJson() methods. These can be used to create a deep clone by first encoding the object to JSON and then decoding it back.
However, for performance reasons, I usually implement a separate clone method instead. It's a few minutes work, but I find that it is often time well spent.
In the example below, cloneSlow uses the JSON-technique, and cloneFast uses the explicitly implemented clone method. The printouts prove that the clone is really a deep clone, and not just a copy of the reference to a.
import 'dart:convert';
class A{
String a;
A(this.a);
factory A.fromMap(Map map){
return A(
map['a']
);
}
Map<String, dynamic> toJson(){
return {
'a': a
};
}
A cloneSlow(){
return A.fromMap(jsonDecode(jsonEncode(this)));
}
A cloneFast(){
return A(
a
);
}
#override
String toString() => 'A(a: $a)';
}
void main() {
A a = A('a');
A b = a.cloneFast();
b.a = 'b';
print('a: $a b: $b');
}
There's no API for cloning/deep-copying built into Dart.
We have to write clone() methods ourselves & (for better or worse) the Dart authors want it that way.
Deep copy Object /w List
If the Object we're cloning has a List of Objects as a field, we need to List.generate that field and those Objects need their own clone method.
Example of cloning method (copyWith()) on an Order class with a List field of objects (and those nested objects also have a copyWith()):
Order copyWith({
int? id,
Customer? customer,
List<OrderItem>? items,
}) {
return Order(
id: id ?? this.id,
customer: customer ?? this.customer,
//items: items ?? this.items, // this will NOT work, it references
items: items ?? List.generate(this.items.length, (i) => this.items[i].copyWith()),
);
}
Gunter mentions this here.
Note, we cannot use List.from(items) nor [...items]. These both only make shallow copies.
Dart does not share Memory within multiple threads (isolate), so...
extension Clone<T> on T {
/// in Flutter
Future<T> clone() => compute<T, T>((e) => e, this);
/// in Dart
Future<T> clone() async {
final receive = ReceivePort();
receive.sendPort.send(this);
return receive.first.then((e) => e as T).whenComplete(receive.close);
}
}
An example of Deep copy in dart.
void main() {
Person person1 = Person(
id: 1001,
firstName: 'John',
lastName: 'Doe',
email: 'john.doe#email.com',
alive: true);
Person person2 = Person(
id: person1.id,
firstName: person1.firstName,
lastName: person1.lastName,
email: person1.email,
alive: person1.alive);
print('Object: person1');
print('id : ${person1.id}');
print('fName : ${person1.firstName}');
print('lName : ${person1.lastName}');
print('email : ${person1.email}');
print('alive : ${person1.alive}');
print('=hashCode=: ${person1.hashCode}');
print('Object: person2');
print('id : ${person2.id}');
print('fName : ${person2.firstName}');
print('lName : ${person2.lastName}');
print('email : ${person2.email}');
print('alive : ${person2.alive}');
print('=hashCode=: ${person2.hashCode}');
}
class Person {
int id;
String firstName;
String lastName;
String email;
bool alive;
Person({this.id, this.firstName, this.lastName, this.email, this.alive});
}
And the output below.
id : 1001
fName : John
lName : Doe
email : john.doe#email.com
alive : true
=hashCode=: 515186678
Object: person2
id : 1001
fName : John
lName : Doe
email : john.doe#email.com
alive : true
=hashCode=: 686393765
// Hope this work
void main() {
List newList = [{"top": 179.399, "left": 384.5, "bottom": 362.6, "right": 1534.5}, {"top": 384.4, "left": 656.5, "bottom": 574.6, "right": 1264.5}];
List tempList = cloneMyList(newList);
tempList[0]["top"] = 100;
newList[1]["left"] = 300;
print(newList);
print(tempList);
}
List cloneMyList(List originalList) {
List clonedList = new List();
for(Map data in originalList) {
clonedList.add(Map.from(data));
}
return clonedList;
}
This works for me.
Use the fromJson and toJson from your Object's Class on JSON serializing
var copy = ObjectClass.fromJson(OrigObject.toJson());
make a helper class:
class DeepCopy {
static clone(obj) {
var tempObj = {};
for (var key in obj.keys) {
tempObj[key] = obj[key];
}
return tempObj;
}
}
and copy what you want:
List cloneList = [];
if (existList.length > 0) {
for (var element in existList) {
cloneList.add(DeepCopy.clone(element));
}
}
Let's say, you want to deep copy an object Person which has an attribute that is a list of other objects Skills. By convention, we use the copyWith method with optional parameters for deep copy, but you can name it anything you want.
You can do something like this
class Skills {
final String name;
Skills({required this.name});
Skills copyWith({
String? name,
}) {
return Skills(
name: name ?? this.name,
);
}
}
class Person {
final List<Skills> skills;
const Person({required this.skills});
Person copyWith({
List<Skills>? skills,
}) =>
Person(skills: skills ?? this.skills.map((e) => e.copyWith()).toList());
}
Keep in mind that using only this.skills will only copy the reference of the list. So original object and the copied object will point to the same list of skills.
Person copyWith({
List<Skills>? skills,
}) =>
Person(skills: skills ?? this.skills);
If your list is primitive type you can do it like this. Primitive types are automatically copied so you can use this shorter syntax.
class Person {
final List<int> names;
const Person({required this.names});
Person copyWith({
List<int>? names,
}) =>
Person(names: names ?? []...addAll(names));
}
The accepted answer doesn't provide an answer, and the highest-rated answer 'doesn't work' for more complex Map types.
It also doesn't make a deep copy, it makes a shallow copy which seems to be how most people land on this page. My solution also makes a shallow copy.
JSON-cloning, which a few people suggest, just seems like gross overhead for a shallow-clone.
I had this basically
List <Map<String, dynamic>> source = [{'sampledata', []}];
List <Map<String, dynamic>> destination = [];
This worked, but of course, it's not a clone, it's just a reference, but it proved in my real code that the data types of source and destination were compatible (identical in my case, and this case).
destination[0] = source[0];
This did not work
destination[0] = Map.from(source[0]);
This is the easy solution
destionation[0] = Map<String, dynamic>.from(source[0]);

For use of constructor in c#

I have a class that has 2 properties and a constructor:
public class Card
{
public int CardName {get;set;}
public bool IsActive {get;set;}
public Card (int cardName, bool isActive)
{
CardName = cardName;
IsActive = isActive;
}
}
How do I force the developer to use the constructor instead of doing the following:
var card = new Card{ CardName = "blab", IsActive = true };
On a side note, what is the statement above called? Is that a lazy loading statement?
You already have.
By not having an empty constructor you've removed the ability to use the object initializer method of creating an object.
This:
var card = new Card{ CardName = "blab", IsActive = true };
is the same as this
var card = new Card() { CardName = "blab", IsActive = true };
And in this context new Card() is not valid.
That depends on why you want to prevent the syntax in question.
The object initializer syntax is shorthand for setting a bunch of properties immediately after construction. That is, this:
var c = new Card { CardName = "foo", IsActive = true };
Is semantically identical to this:
var c = new Card();
c.CardName = "foo";
c.IsActive = true;
In both cases, a constructor does run, but its immediately followed by a series of property initializers to apply to the new object.
In your case, since there is no parameterless constructor, you cannot use the object initializer syntax the way you posted. However, it is legal to pass constructor parameters along with the object initializer, so the following would be legal for your class:
var c = new Card("", false) { CardName = "foo", IsActive = true };
(One could argue that this syntax makes the meaning of values more clear than simply passing them to a constructor; one could also argue its just being excessively stubborn :) I could go either way)
You could prevent this second syntax from working by removing the public setters for those properties. If your goal is to prevent the user from changing the values passed into the constructor, making an immutable Card object, for example, that would be the way to go.
I should point out, though, that if one of my juniors asked me this question at work I'd really want to know why they found it necessary to prevent object initialization from being used. There are valid reasons, of course, but they are usually not the source of the question. Object initializers are a good thing -- there are cases where this syntax is very convenient (particularly with LINQ) and I use it all the time.
If you do some kind of setup in the constructor based on the initial values, but those properties are public-settable, you already have to deal with a case where the user changes those values after construction. If your goal is merely to ensure that some "setup" code happens when the object is first constructed, put that code into a default constructor and chain them together:
public class Card
{
public string CardName { get; set; }
public bool IsActive { get; set; }
public Card()
{
// setup code here.
}
public Card ( string name, bool active )
: this()
{
this.CardName = name;
this.IsActive = active;
}
}
Declare the getters of the property as 'Private'.
Something like Public int CardName {private get; set;}.

Custom transformation function throwing error.

This is my transformation function call:
<p><%# MyFunctions.getDocumentCategory(Eval("DocumentID"))%></p>
This is the function:
public static string getDocumentCategory(int documentID)
{
string category;
StringBuilder sb = new StringBuilder();
// Get document categories
var ds = CategoryInfoProvider.GetDocumentCategories(documentID, "CategoryEnabled = 1", null);
// Check whether exists at least one category
if (!DataHelper.DataSourceIsEmpty(ds))
{
// Loop thru all categories
foreach (DataRow dr in ds.Tables[0].Rows)
{
sb.Append(Convert.ToString(dr["CategoryDisplayName"]) + ",");
}
}
string content = sb.ToString();
category = content.Split(',')[0];
return category;
}
}
This is the error:
MyFunctions.getDocumentCategory(int) has some invalid arguments.
I've tried an alternate form of the function that accepts strings rather than ints but it throws the same error. I've verified that the Eval("DocumentID") works correctly when placed by itself. Any ideas?
Eval returns an object. You either need to convert it to an int, or change the function to accept an object, and convert that object to an int.
<p><%# MyFunctions.getDocumentCategory( Convert.ToInt32( Eval("DocumentID") ) )%></p>
OR
public static string getDocumentCategory(object document)
{
int documentID = Convert.ToInt32( document );
etc...
}
Thanks to Doozer for the nice explanation and example.
The second approach - to accept the object and make the conversion inside your custom function - may be better to keep the transformation code cleaner. The result is equal.
Just to add a little bit - you can use Kentico's ValidationHelper for conversions, for example:
transformation:
<%# MyFunctions.getDocumentCategory(Eval("DocumentID"))%>
code:
public static string getDocumentCategory(object docID)
{
int documentID = ValidationHelper.GetInteger(docID, 0); //0 is the default value
...

How to query by partitionkey in Azure Table Storage?

I have the following TableServiceContext class for books, I want to query the table Books by the partitionKey, please ignore the fact that
I'm using the partition key as the book name, this is just for my learning sakes
public class BookDataServiceContext: TableServiceContext
{
public BookDataServiceContext(string baseAddress, StorageCredentials credentials)
: base(baseAddress, credentials)
{
}
public IQueryable<Book> Books
{
get
{
return this.CreateQuery<Book>("Books");
}
}
public void AddMessage(string name, int value)
{
this.AddObject("Books", new Book {PartitionKey=name, BookName = name, BookValue = value});
this.SaveChanges();
}
public Book GetBookByPartitionKey(Guid partitionKey)
{
var qResult = this.CreateQuery<Book>("Books");
This doesnt work ----> // qResult = qResult.Where(e => (e.PartitionKey.CompareTo(partitionKey)==0));
}
}
I get a "Cannot implicitly convert type 'System.Linq.IQueryable' to 'System.Data.Services.Client.DataServiceQuery'. An explicit conversion exists (are you missing a cast?)" on that last line.
Any help will be appreciated!
qResult is already assigned a type by the compiler. You're trying to re-assign it to a different type, but that isn't allowed.
Try this
var someOtherName = qResult.Where(e => (e.PartitionKey.CompareTo(partitionKey)==0));
Edit: It looks like your Books property is the wrong type.
public DataServiceQuery<Book> Books
{
get
{
return this.CreateQuery<Book>("Books");
}
}
public Book GetBookByPartitionKey(string partitionKey)
{
var qResult = Books.Where(e => (e.PartitionKey.CompareTo(partitionKey)==0));
}

Resources