473,700 Members | 2,538 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Why is concept of equals and operator== implemented this way?

Why can I overload operator== and operator!= separately having different
implementations and additionally I can override equals() also having a
different implementation.

Why not forbid overloading of == and != but instead translate each call
of objA==objB automatically in System.Object.E quals(objA, objB).

This would remove inconsistencies like

myString1==mySt ring2

and

(object)myStrin g1==(object)myS tring2

having different results.

also, should operator!= not always return the negated value of!=?
So why is it good for?

I would like to understand the technical reason for that, if there was any.
Jun 17 '06 #1
12 2201
cody <de********@gmx .de> wrote:
Why can I overload operator== and operator!= separately having different
implementations and additionally I can override equals() also having a
different implementation.

Why not forbid overloading of == and != but instead translate each call
of objA==objB automatically in System.Object.E quals(objA, objB).
'==' is resolved statically, while Object.Equals(o bject) is determined
by dynamic dispatch. The simplest answer is: performance, both in
textual code size (see below) and in runtime execution.
This would remove inconsistencies like

myString1==mySt ring2

and

(object)myStrin g1==(object)myS tring2

having different results.
It would also make the '==' operator always perform a dynamic dispatch
(i.e. a virtual method call). Not only would it be slower, but it would
also make it harder to (for example) program safely with multithreaded
locks.

When you call a virtual method, you've got no idea what code is going to
be called. That's one of the reasons why it isn't recommended to call
virtual methods while holding a lock. If things were to work this way,
no one could safely compare object references while holding locks,
unless they used the cumbersome object.Referenc eEquals(object, object)
method.

Also, it is not always possible to override the correct Equals. If the
two sides of the '==' are of different type, which side would the
compiler generate a call to .Equals for? What if one side is a Framework
type like int, and the other is a complex number type?
also, should operator!= not always return the negated value of!=?
So why is it good for?


This question I cannot answer, since I've never had a reason to have a
different implementation.

-- Barry

--
http://barrkel.blogspot.com/
Jun 17 '06 #2
Barry Kelly wrote:
cody <de********@gmx .de> wrote:
Why can I overload operator== and operator!= separately having different
implementations and additionally I can override equals() also having a
different implementation.

Why not forbid overloading of == and != but instead translate each call
of objA==objB automatically in System.Object.E quals(objA, objB).
'==' is resolved statically, while Object.Equals(o bject) is determined
by dynamic dispatch. The simplest answer is: performance, both in
textual code size (see below) and in runtime execution.


even if making unrealistic micro benchmarks with empty method bodies
there is almost no difference between normal methods and virtual ones.
When you call a virtual method, you've got no idea what code is going to
be called. That's one of the reasons why it isn't recommended to call
virtual methods while holding a lock. If things were to work this way,
no one could safely compare object references while holding locks,
unless they used the cumbersome object.Referenc eEquals(object, object)
method.
This sounds logical at first, but in fact, but looking into microsofts
shared source cli implementation, almost all implementations of
operator== is calling Equals() and the very few ones not doing this are
accessing properties of the object which are in some cases also virtual
or calling virtual methods internally.
Also, it is not always possible to override the correct Equals. If the
two sides of the '==' are of different type, which side would the
compiler generate a call to .Equals for? What if one side is a Framework
type like int, and the other is a complex number type?


Well, I see the problem. But in reality I've never seen an
implementation of operator== for different types. Did you?
I cannot imagine a scenario where this would be necessary, given the
fact that objects of different types should per definition never be
considered to be equal, and even if, you can implement an implicit
conversion operator for that.
also, should operator!= not always return the negated value of!=?
So why is it good for?


This question I cannot answer, since I've never had a reason to have a
different implementation.


Indeed very strange. even comparisons with NaN or nullable types
involved, operator!= always yields the opposite value of the
corresponding operator==:

Console.WriteLi ne(double.NaN == double.NaN); // false
Console.WriteLi ne(double.NaN != double.NaN); // true
Console.WriteLi ne(float.NaN == float.NaN); // false
Console.WriteLi ne(float.NaN != float.NaN); // true
Console.WriteLi ne((float?)1 == (float?)null); // false
Console.WriteLi ne((float?)1 != (float?)null); // true

In conclusion, I still feel that the concepts of ==,!= and equals could
have been implemented in a simpler and more logical way in .NET.
Maybe the current implementation may be 1% faster than the simpler one
and you can do very strange stuff like == and != returning the same
value or making objects of different types equal but if that makes 99.9%
of all normal cases harder to write and to maintain this is too much to pay.
Jun 17 '06 #3
cody <de********@gmx .de> wrote:
Barry Kelly wrote:
cody <de********@gmx .de> wrote:
Why not forbid overloading of == and != but instead translate each call
of objA==objB automatically in System.Object.E quals(objA, objB).
'==' is resolved statically, while Object.Equals(o bject) is determined
by dynamic dispatch. The simplest answer is: performance, both in
textual code size (see below) and in runtime execution.


even if making unrealistic micro benchmarks with empty method bodies
there is almost no difference between normal methods and virtual ones.


Unless it's been overloaded, '==' isn't a method call.
When you call a virtual method, you've got no idea what code is going to
be called. That's one of the reasons why it isn't recommended to call
virtual methods while holding a lock. If things were to work this way,
no one could safely compare object references while holding locks,
unless they used the cumbersome object.Referenc eEquals(object, object)
method.


This sounds logical at first, but in fact, but looking into microsofts
shared source cli implementation, almost all implementations of
operator== is calling Equals() and the very few ones not doing this are
accessing properties of the object which are in some cases also virtual
or calling virtual methods internally.


What you seem to be advocating is to turn *every* *usage* of '==' with
reference types into a method call, but it isn't currently. What you've
been looking up in the SSCLI is the overloaded '==' operator on various
types. The built-in '==' operator for reference types has different
semantics.
Also, it is not always possible to override the correct Equals. If the
two sides of the '==' are of different type, which side would the
compiler generate a call to .Equals for? What if one side is a Framework
type like int, and the other is a complex number type?


Well, I see the problem. But in reality I've never seen an
implementation of operator== for different types. Did you?


Yes. I've implemented them, for my own Date type.
I cannot imagine a scenario where this would be necessary, given the
fact that objects of different types should per definition never be
considered to be equal, and even if, you can implement an implicit
conversion operator for that.
There was a conversion operator too, but why convert when you can
compare as-is?
In conclusion, I still feel that the concepts of ==,!= and equals could
have been implemented in a simpler and more logical way in .NET.
Maybe the current implementation may be 1% faster than the simpler one
and you can do very strange stuff like == and != returning the same
value or making objects of different types equal but if that makes 99.9%
of all normal cases harder to write and to maintain this is too much to pay.


I will submit this contrived micro-benchmark in favour of the current
situation, if only to point out some of the overhead of virtual method
calls on Equals etc.:

---8<---
using System;
using System.Collecti ons.Generic;
using System.Diagnost ics;
using System.Text;
using System.Runtime. CompilerService s;

class SomeObject
{
[MethodImpl(Meth odImplOptions.N oInlining)]
public override bool Equals(object obj)
{
// This would be the only way to perform reference equality
// checks if the proposed idea was implemented.
return object.Referenc eEquals(this, obj);
}

[MethodImpl(Meth odImplOptions.N oInlining)]
public static bool operator==(Some Object left, SomeObject right)
{
return object.Referenc eEquals(left, right);
}

[MethodImpl(Meth odImplOptions.N oInlining)]
public static bool operator!=(Some Object left, SomeObject right)
{
return !object.Referen ceEquals(left, right);
}

[MethodImpl(Meth odImplOptions.N oInlining)]
public override int GetHashCode()
{
return base.GetHashCod e();
}
}

class App
{
delegate void Method();

static void Benchmark(int iterations, string label, Method method)
{
method(); // warmup

Stopwatch start = Stopwatch.Start New();
for (int i = 0; i < iterations; ++i)
method();
Console.WriteLi ne("{0,20} : {1,6:f3} ({2} iterations)",
label,
start.ElapsedTi cks / (double) Stopwatch.Frequ ency,
iterations);
}

static void Main()
{
const int iterCount = 30;
const int objectCount = 10000000;

// To eliminate "unused value" optimizations.
int equalCount = 0;

SomeObject[] list = new SomeObject[objectCount];
for (int i = 0; i < objectCount; ++i)
list[i] = new SomeObject();

Benchmark(iterC ount, "Overloaded '=='", delegate
{
for (int i = 0; i < list.Length; ++i)
if (list[i] == null)
++equalCount;
});

Benchmark(iterC ount, "Overridden 'Equals'", delegate
{
for (int i = 0; i < list.Length; ++i)
if (list[i].Equals(null))
++equalCount;
});

Benchmark(iterC ount, "Object '=='", delegate
{
for (int i = 0; i < list.Length; ++i)
if ((object) list[i] == null)
++equalCount;
});

Benchmark(iterC ount, "RefEquals" , delegate
{
for (int i = 0; i < list.Length; ++i)
if (object.Referen ceEquals(list[i], null))
++equalCount;
});

Console.WriteLi ne("Total EqualCount: {0}", equalCount);
}
}
--->8---

On my system:

---8<---
Overloaded '==' : 1.582 (30 iterations)
Overridden 'Equals' : 2.662 (30 iterations)
Object '==' : 0.609 (30 iterations)
RefEquals : 0.896 (30 iterations)
Total EqualCount: 0
--->8---

Of limited applicability, very contrived, usual disclaimers, etc. etc...

-- Barry

--
http://barrkel.blogspot.com/
Jun 17 '06 #4
Barry Kelly wrote:
cody <de********@gmx .de> wrote:
Barry Kelly wrote:
cody <de********@gmx .de> wrote:

Why not forbid overloading of == and != but instead translate each call
of objA==objB automatically in System.Object.E quals(objA, objB).
'==' is resolved statically, while Object.Equals(o bject) is determined
by dynamic dispatch. The simplest answer is: performance, both in
textual code size (see below) and in runtime execution.

even if making unrealistic micro benchmarks with empty method bodies
there is almost no difference between normal methods and virtual ones.


Unless it's been overloaded, '==' isn't a method call.


Yes that is true. If == couldn't be overloaded the system would always
have to call Object.Equals() and this could not optimized to a single IL
instruction as it now is. One either would have to call
Object.Referenc eEquals() explicitly (which then could be inlined),
or an operator=== like it is in PHP would have to be introduced.
Also, it is not always possible to override the correct Equals. If the
two sides of the '==' are of different type, which side would the
compiler generate a call to .Equals for? What if one side is a Framework
type like int, and the other is a complex number type?

System.Object.E quals(objA, objB) only calls Equals of the first
parameter. So you always would have to write if (myComplexNumbe r==1.5).
I think it is very intuitive having the own or most specialized type on
the left side, at least for me. Sure, when making the call the other way
around then always false is returned. But when the types are known at
compile time, an appropriate Equals method doesn't exist and the
compiler determines an appropriate Equals method exists for the other
way around then a warning could be issued.
Well, I see the problem. But in reality I've never seen an
implementation of operator== for different types. Did you?


Yes. I've implemented them, for my own Date type.


Which type does it compare with? Your own type with System.Datetime ?
Now as you say it, I can remember doing exactly the same thing because
we needed a Date class for our project which can be null. It was so long
ago I couldn't remember it, sorry :)
But this is an interesting case. We have different types
(System.DateTim e and our own), but each represents exactly the same
entity, therefore users expect that they are comparable with each other.
I cannot imagine a scenario where this would be necessary, given the
fact that objects of different types should per definition never be
considered to be equal, and even if, you can implement an implicit
conversion operator for that.


There was a conversion operator too, but why convert when you can
compare as-is?


Well, I can see there can indeed be a big performance difference between
always creating a new object just for equality testing and just
comparing some fields against each other, but in the date case you just
encapsulate a Datetime so no creation of a new object is necessary.
In conclusion, I still feel that the concepts of ==,!= and equals could
have been implemented in a simpler and more logical way in .NET.
Maybe the current implementation may be 1% faster than the simpler one
and you can do very strange stuff like == and != returning the same
value or making objects of different types equal but if that makes 99.9%
of all normal cases harder to write and to maintain this is too much to pay.


I will submit this contrived micro-benchmark in favour of the current
situation, if only to point out some of the overhead of virtual method
calls on Equals etc.:

---8<---
using System;
using System.Collecti ons.Generic;
using System.Diagnost ics;
using System.Text;
using System.Runtime. CompilerService s;

class SomeObject
{
[MethodImpl(Meth odImplOptions.N oInlining)]
public override bool Equals(object obj)
{
// This would be the only way to perform reference equality
// checks if the proposed idea was implemented.
return object.Referenc eEquals(this, obj);
}

[MethodImpl(Meth odImplOptions.N oInlining)]
public static bool operator==(Some Object left, SomeObject right)
{
return object.Referenc eEquals(left, right);
}

[MethodImpl(Meth odImplOptions.N oInlining)]
public static bool operator!=(Some Object left, SomeObject right)
{
return !object.Referen ceEquals(left, right);
}

[MethodImpl(Meth odImplOptions.N oInlining)]
public override int GetHashCode()
{
return base.GetHashCod e();
}
}

class App
{
delegate void Method();

static void Benchmark(int iterations, string label, Method method)
{
method(); // warmup

Stopwatch start = Stopwatch.Start New();
for (int i = 0; i < iterations; ++i)
method();
Console.WriteLi ne("{0,20} : {1,6:f3} ({2} iterations)",
label,
start.ElapsedTi cks / (double) Stopwatch.Frequ ency,
iterations);
}

static void Main()
{
const int iterCount = 30;
const int objectCount = 10000000;

// To eliminate "unused value" optimizations.
int equalCount = 0;

SomeObject[] list = new SomeObject[objectCount];
for (int i = 0; i < objectCount; ++i)
list[i] = new SomeObject();

Benchmark(iterC ount, "Overloaded '=='", delegate
{
for (int i = 0; i < list.Length; ++i)
if (list[i] == null)
++equalCount;
});

Benchmark(iterC ount, "Overridden 'Equals'", delegate
{
for (int i = 0; i < list.Length; ++i)
if (list[i].Equals(null))
++equalCount;
});

Benchmark(iterC ount, "Object '=='", delegate
{
for (int i = 0; i < list.Length; ++i)
if ((object) list[i] == null)
++equalCount;
});

Benchmark(iterC ount, "RefEquals" , delegate
{
for (int i = 0; i < list.Length; ++i)
if (object.Referen ceEquals(list[i], null))
++equalCount;
});

Console.WriteLi ne("Total EqualCount: {0}", equalCount);
}
}
--->8---

On my system:

---8<---
Overloaded '==' : 1.582 (30 iterations)
Overridden 'Equals' : 2.662 (30 iterations)
Object '==' : 0.609 (30 iterations)
RefEquals : 0.896 (30 iterations)
Total EqualCount: 0
--->8---


Having a closer look comparing my and your benchmark I noticed that I
was calling the virtual methods always on the same object in a loop so
the jit could cache the method pointer in a register, no wonder why
virtual methods are nearly as fast as normal ones then :)

Running the release exe without the IDE (using .net 2.0) the
ReferenceEquals always runs faster than Object== on my computer.
But if I remove the NoInline attribute, ReferenceEquals is slower as
Object==.

overridden : 3,401 (30 iterations)
normal : 2,725 (30 iterations)
static : 1,212 (30 iterations)
Overloaded '==' : 0,716 (30 iterations)
Overridden 'Equals' : 3,428 (30 iterations)
Object '==' : 1,104 (30 iterations)
RefEquals : 0,898 (30 iterations)
Total EqualCount: 0
Jun 18 '06 #5
On Sat, 17 Jun 2006 18:32:13 +0200, cody <de********@gmx .de> wrote:
Why not forbid overloading of == and != but instead translate each call
of objA==objB automatically in System.Object.E quals(objA, objB).
1. Upcasting to object involves boxing & unboxing for value types, and
that's a very expensive operation. You absolutely want to avoid that
for something as frequently used as an equality test.

2. Even with reference types, you're overriding a method that takes
object parameters, so your own Equals override will have to perform
cumbersome type checking on the supplied objects.

Now that we have generics, both issues could be avoided with a generic
Equals method; unfortunately that was not available back when the CLR
was designed. So strongly-typed equality tests were necessary back
then, and strongly-typed methods can't be inherited from Object.
also, should operator!= not always return the negated value of!=?


Yeah, that's a good point. operator!= could be auto-generated.
--
http://www.kynosarges.de
Jun 18 '06 #6
Chris Nahr wrote:
On Sat, 17 Jun 2006 18:32:13 +0200, cody <de********@gmx .de> wrote:
Why not forbid overloading of == and != but instead translate each call
of objA==objB automatically in System.Object.E quals(objA, objB).
1. Upcasting to object involves boxing & unboxing for value types, and
that's a very expensive operation. You absolutely want to avoid that
for something as frequently used as an equality test.


structs do not have a default implementation of operator==. If you want
some you could implement a suitable equals method having the appropriate
value type as parameter and the compiler translates a call of
myStruct1==mySt ruct2 into a call to myStruct1.Equal s(myStruct2) so that
MyStruct.Equals (MyStruct obj) is called.
2. Even with reference types, you're overriding a method that takes
object parameters, so your own Equals override will have to perform
cumbersome type checking on the supplied objects.
Sure it will have to, but honestly how often do you use == for objects
that are *no* value types and *no* strings (which are sealed) both
require no type checks. In collection methods like IndexOf the non-type
safe version of Equals is used and type checks have to be performed anyway.
For most other cases you want reference equality anyway for which an
operator=== could be used.

And as I said, nobody prevents you from implementing a strongly typed
version of Equals which will then be picked by the compiler and here
also is no type check necessary.
Now that we have generics, both issues could be avoided with a generic
Equals method; unfortunately that was not available back when the CLR
was designed. So strongly-typed equality tests were necessary back
then, and strongly-typed methods can't be inherited from Object.


Iam not sure in which way generics can help here.
also, should operator!= not always return the negated value of!=?


Yeah, that's a good point. operator!= could be auto-generated.


The same applies to operator< and operator>= vs operator> and
operator<= or operator==(Y a,X b) vs operator==(X b,Y a) or
operator'true' vs operator'false' .
Jun 18 '06 #7
cody <de********@gmx .de> wrote:
2. Even with reference types, you're overriding a method that takes
object parameters, so your own Equals override will have to perform
cumbersome type checking on the supplied objects.
Sure it will have to, but honestly how often do you use == for objects
that are *no* value types and *no* strings (which are sealed) both
require no type checks. In collection methods like IndexOf the non-type
safe version of Equals is used and type checks have to be performed anyway.


Referential equality for mutable types has completely different
semantics from value equality, which is used for strings. With the
greatest respect, I use referential equality far, far, far more often
than value equality.

Taking something out of thin air:

Foo f = new Foo();
Foo f2 = new Foo();
Console.WriteLi ne(f == f2);

How often, in your programs, do you require this to print "True" on the
console? Speaking for myself, almost *never*.
For most other cases you want reference equality anyway for which an
operator=== could be used.
Here, it seems to me, you are introducing a new operator in order to do
what most people already use '==' for.
And as I said, nobody prevents you from implementing a strongly typed
version of Equals which will then be picked by the compiler and here
also is no type check necessary.


But: this is advocating making an expensive boxing operation the
default. That approach might be more reasonable in a more dynamic
language like Lisp or Python, but it isn't right in a language with a
C-based history.

-- Barry

--
http://barrkel.blogspot.com/
Jun 18 '06 #8
Barry Kelly <ba***********@ gmail.com> wrote:
Sure it will have to, but honestly how often do you use == for objects
that are *no* value types and *no* strings (which are sealed) both
require no type checks. In collection methods like IndexOf the non-type
safe version of Equals is used and type checks have to be performed anyway.


Referential equality for mutable types has completely different
semantics from value equality, which is used for strings. With the
greatest respect, I use referential equality far, far, far more often
than value equality.

Taking something out of thin air:

Foo f = new Foo();
Foo f2 = new Foo();
Console.WriteLi ne(f == f2);

How often, in your programs, do you require this to print "True" on the
console? Speaking for myself, almost *never*.


Actually, I rarely compare things which *don't* overload equality. I
rarely check for references being identical, but I often check for
strings being equal, for instance.

I often compare value types for equality, however.

Out of interest, what do you tend to use reference identity tests for?

--
Jon Skeet - <sk***@pobox.co m>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jun 18 '06 #9
"Barry Kelly" <ba***********@ gmail.com> wrote in message
news:oi******** *************** *********@4ax.c om...

Referential equality for mutable types has completely different
semantics from value equality, which is used for strings.


Hmmm...I thought all identical strings were folded to the same reference. Or
am I thinking of a completely different language?

///ark
Jun 18 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
10043
by: #Hai | last post by:
Hi, What is the difference between Object.Equals and "==" operator ? When we use CollectionBase.List.Remove(object), which methods is used to compare objects ? Thanks
2
9362
by: emma middlebrook | last post by:
Hi Having difficulty getting myself clear on how a type's operator== fits in with Object.Equals. Let's just consider reference types. The default operator== tests for object identity (reference) equivalence. You can override it if you like.
17
7448
by: Zeng | last post by:
I'm trying to comparing 2 objects (pointer to object) to see if they are the "same" as each other. Here is what the definition of being the "same" object type for both objects, object 1, object 2, same? ----------------------------------------------------------- Decimal 199677 199677 yes String "hello" "hello" yes null null yes
3
17647
by: Fei Li | last post by:
Hi, take string class as an example, who can explain the difference? Thanks
4
2539
by: Kurt | last post by:
Wouldn't you agree all of the follwoing should produce the same result? r = (o1 == o2); r = (o2 == o1); r = object.Equals(o1, o2); r = object.Equals(o2, o1); r = (o1.Equals(o2)); r = (o2.Equals(o1));
4
3206
by: Chris | last post by:
This is something that has been bugging me for some time. When exactly should I be using == instead of .Equals() ? I see a lot of code that performs object evaluation e.g. Is Object1 the same as Object2 by using == which works but shouldn't it be using .Equals()? e.g. Object1.Equals(Object2) I believe == should be using for simple type evaluation e.g. int a = 0;
18
4739
by: JohnR | last post by:
From reading the documentation, this should be a relatively easy thing. I have an arraylist of custom class instances which I want to search with an"indexof" where I'm passing an instance if the class where only the "searched" property has a value. I expected to get the index into the arraylist where I could then get the entire class instance. However, the 'indexof' is never calling my overloaded, overrides Equals method. Here is the...
8
3741
by: Kenneth Baltrinic | last post by:
When one overrides the Equals() method of an object, one is supposed to override GetHashCode() as well and this makes good sense. But I have seen lots of people who do this and do not override the == and != opperators. Am I missing something or when would one want to have different implementations for Equals and ==? --Ken
10
105189
by: r035198x | last post by:
The Object class has five non final methods namely equals, hashCode, toString, clone, and finalize. These were designed to be overridden according to specific general contracts. Other classes that make use of these methods assume that the methods obey these contracts so it is necessary to ensure that if your classes override these methods, they do so correctly. In this article I'll take a look at the equals and hashCode methods. ...
0
8726
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8645
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9075
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
8973
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8925
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
6561
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
4657
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3089
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2392
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.