473,396 Members | 1,840 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

Generic methods

I'm quite new to generics. I have 2 generic classes:
MyClass<Tand MyOtherClass<T>.
MyClass<Thas 2 public Add methods
Add(MyOtherClass<T>);
Add(MyOtherClass<Wrapper<T>>); (Wrapper<Tis another class that
contains an object of type T)

I have a third generic class: MyHandler<Twhich contains 2 Add
methods and a generic method:
Add(T obj)
{
Add<T>(obj);
}
Add(Wrapper<Tobj)
{
Add<Wrapper<T>>(obj);
}
Add<E>(E obj)
{
MyOtherClass<Eobj1 = new MyOtherClass<E>();
MyClass<Tobj2 = new MyClass<T>();
obj2.Add(obj1);
}

The compiler complains about obj2.Add(obj1) that "cannot convert from
MyOtherClass<Eto MyOtherClass<T>"

why doesn't this work? How should I be doing it?

very grateful for your help.
Thanks
Phil

Aug 23 '07 #1
10 2679
ph*****@googlemail.com wrote:
The compiler complains about obj2.Add(obj1) that "cannot convert from
MyOtherClass<Eto MyOtherClass<T>"

why doesn't this work? How should I be doing it?
If E is not the same as T, then passing a MyOtherClass<Ein place of a
MyOtherClass<Tisn't legal. Even if E and T are related by
inheritance, it's not allowed, and I don't even see anything in your
code that suggests they are.

How you _should_ be doing it, I'm not sure. It depends on what you're
trying to do here. Why is the method generic? The code you posted
doesn't appear to do anything with the parameter anyway. So it's
unclear how you are using it.

If you expect to always be using with an object compatible with T, then
perhaps you can take advantage of that. For example, if E inherits T:

Add<E>(E obj) where E : T
{
MyOtherClass<Tobj1 = new MyOtherClass<T>();
MyClass<Tobj2 = new MyClass<T>();

/* Presumably somewhere, either in the above constructors
or later on, you use "obj" in some way related to the
T-based generic instances above. In that context,
because it's been constrained to inherit T, you can use
the "obj" parameter wherever you'd need a T */

obj2.Add(obj1);
}

It's difficult to give a nice specific answer, because the code you
posted doesn't explain why the method is the way it is. We can't really
tell what it is exactly you want to do. Another way to fix the problem
would be to use "E" instead of "T" everywhere in the method, but again,
without knowing why you wrote the method that way, it's hard to know if
that's a suitable answer.

Pete
Aug 23 '07 #2
On 23 Aug, 01:18, Peter Duniho <NpOeStPe...@NnOwSlPiAnMk.comwrote:
phan...@googlemail.com wrote:
The compiler complains about obj2.Add(obj1) that "cannot convert from
MyOtherClass<Eto MyOtherClass<T>"
why doesn't this work? How should I be doing it?

If E is not the same as T, then passing a MyOtherClass<Ein place of a
MyOtherClass<Tisn't legal. Even if E and T are related by
inheritance, it's not allowed, and I don't even see anything in your
code that suggests they are.

How you _should_ be doing it, I'm not sure. It depends on what you're
trying to do here. Why is the method generic? The code you posted
doesn't appear to do anything with the parameter anyway. So it's
unclear how you are using it.

If you expect to always be using with an object compatible with T, then
perhaps you can take advantage of that. For example, if E inherits T:

Add<E>(E obj) where E : T
{
MyOtherClass<Tobj1 = new MyOtherClass<T>();
MyClass<Tobj2 = new MyClass<T>();

/* Presumably somewhere, either in the above constructors
or later on, you use "obj" in some way related to the
T-based generic instances above. In that context,
because it's been constrained to inherit T, you can use
the "obj" parameter wherever you'd need a T */

obj2.Add(obj1);
}

It's difficult to give a nice specific answer, because the code you
posted doesn't explain why the method is the way it is. We can't really
tell what it is exactly you want to do. Another way to fix the problem
would be to use "E" instead of "T" everywhere in the method, but again,
without knowing why you wrote the method that way, it's hard to know if
that's a suitable answer.

Pete
ok, sorry, I was trying to simplify.
ObjectHandler<Tis my DAL object handler dealing with objects that
all derive from a BaseObject so ObjectHandler<Location>,
ObjectHandler<Personetc.
This has a choice of Add Methods that take an object as a parameter.
The object is either AddRequest<Locationetc or
AddRequest<Wrapper<Location>etc because sometimes in my Business
Layer I add some information to the basic object by wrapping it. The
Data Access Layer works fine in NUnit tests where I either pass an
AddRequest<objector an AddRequest<Wrapper<object>>.

My Business Layer has an ObjectManager<Twhere T is also a BaseObject
so ObjectManager<Locationetc. In the Add method of this manager,
sometimes I want to pass the object untouched through to the DAL so I
will use AddRequest<Location>, sometimes I need to attach some more
info so I want to use AddRequest<Wrapper<Location>>.

So the public ObjectManager<T>.Add takes an object of type T. I then
have 2 protected internal AddObject methods, one takes an object of
type T, one takes a Wrapper<Tbecause internal to the Business Layer
I could be adding either kind of object. What I was trying to do then
was call a generic method AddObject<E>(E obj) where this method would
then call down to the DAL using an AddRequest<E>, so:
ObjectManager<T>.Add(T obj)
{
AddObject<T>(obj);
}
ObjectManager<Wrapper<T>>.Add(Wrapper<Tobj)
{
AddObject<Wrapper<T>>(obj);
}

Have I explained it well enough? So as far as I can tell, if
AddObject<Eis called with an object of type T, then the call to the
DAL will use an AddRequest<Twhich will map to the overloaded method
that takes an AddRequest<Ttype parameter. And if AddObject<Eis
called with a Wrapper<Tthen it will use an AddRequest<Wrapper<T>>
which will map to that overloaded method.

Your help is greatly appreciated.

Thanks

Aug 23 '07 #3
ph*****@googlemail.com wrote:
[...]
Have I explained it well enough? So as far as I can tell, if
AddObject<Eis called with an object of type T, then the call to the
DAL will use an AddRequest<Twhich will map to the overloaded method
that takes an AddRequest<Ttype parameter. And if AddObject<Eis
called with a Wrapper<Tthen it will use an AddRequest<Wrapper<T>>
which will map to that overloaded method.
It's late, so maybe I'm not getting it. But here's what I think I
understand:

The key here is that you don't want to write two AddObject() methods,
one that takes the T, and one that takes the Wrapper<T>. You'd prefer
to have a single AddObject() method that can take either a T or a
Wrapper<T>.

Is that right?

If so, I believe the issue is that the compiler, at the line at which
the error occurs, has no way to know that T is related to E in the way
that you know it is.

I played around with constraints a little bit. Okay, a lot. Probably
more than I should have bothered with. :) There are ways to cram the
design into generics using constraints and a shared interface between
the real class and the Wrapper<Tclass, but the result really still
isn't exactly what you're looking for. I think that if generics
supported covariance between declared types, you could get it to work
more easily using constraints. But it doesn't, so you can't.

IMHO, the simplest thing is to just do overloaded versions of that
method, just as you've done elsewhere.

If you really really want to be able to use overloaded methods, I'd say
that the solution is to take a step back and rethink the overall design.
As the design exists right now, I'm not convinced there's any way to
do what you want, because of the lack of any defined relationship
between the two classes.

Now, all that said, I _am_ up way too late, and I'm hardly an expert in
generics to start with. So, maybe someone else has something more
encouraging to offer you. :)

Pete
Aug 23 '07 #4
On 23 Aug, 11:51, Peter Duniho <NpOeStPe...@NnOwSlPiAnMk.comwrote:
phan...@googlemail.com wrote:
[...]
Have I explained it well enough? So as far as I can tell, if
AddObject<Eis called with an object of type T, then the call to the
DAL will use an AddRequest<Twhich will map to the overloaded method
that takes an AddRequest<Ttype parameter. And if AddObject<Eis
called with a Wrapper<Tthen it will use an AddRequest<Wrapper<T>>
which will map to that overloaded method.

It's late, so maybe I'm not getting it. But here's what I think I
understand:

The key here is that you don't want to write two AddObject() methods,
one that takes the T, and one that takes the Wrapper<T>. You'd prefer
to have a single AddObject() method that can take either a T or a
Wrapper<T>.

Is that right?

If so, I believe the issue is that the compiler, at the line at which
the error occurs, has no way to know that T is related to E in the way
that you know it is.

I played around with constraints a little bit. Okay, a lot. Probably
more than I should have bothered with. :) There are ways to cram the
design into generics using constraints and a shared interface between
the real class and the Wrapper<Tclass, but the result really still
isn't exactly what you're looking for. I think that if generics
supported covariance between declared types, you could get it to work
more easily using constraints. But it doesn't, so you can't.

IMHO, the simplest thing is to just do overloaded versions of that
method, just as you've done elsewhere.

If you really really want to be able to use overloaded methods, I'd say
that the solution is to take a step back and rethink the overall design.
As the design exists right now, I'm not convinced there's any way to
do what you want, because of the lack of any defined relationship
between the two classes.

Now, all that said, I _am_ up way too late, and I'm hardly an expert in
generics to start with. So, maybe someone else has something more
encouraging to offer you. :)

Pete
It's not late here in the UK but I still don't get it! :o)

Ideally I want one method in the Business Layer that calls down to the
DAL whether I am using T or Wrapper<T>. There is an overloaded method
in the DAL that takes either AddRequest<Tor AddRequest<Wrapper<T>>
as a parameter.

So what I want to know is why the method in the Business Layer :
AddObject<E>(E obj) which then creates an AddRequest<Ecannot use
this AddRequest<Eto call down to the DAL because that AddRequest<E>
will definitely be either an AddRequest<Tor an
AddRequest<Wrapper<T>for definite. Now that I write this more
clearly I start to understand that the compiler does not know that
another object might be sent to this method. What I need is to be able
to tell it that E is either T or Wrapper<Tbut I don't think this is
possible. I suppose I will need to use overloaded methods here but I
was trying to avoid that because all of the code is actually generic
for that method on the assumption you know it is only one of these 2
types that will be sent in :o(

If anyone has any further advice I would appreciate it.
Phil

Aug 23 '07 #5
Are you essentially looking to have a generic access point in you DAL
for save / load?

If so generics and constraints will work.

Assuming we have an interface ISaveableBusObj
And we have I_TAccessibleWrapper - this interface will define a method
called T getmyObj<T>()

We could have

public class dataLayer
{
public bool saveMyObj<T>(T objToSave) where T : ISaveableObj
{ ... }

public bool saveMyObj<T,W>(W wrapper) where T : ISaveableObj
where W : I_TAccessibleWrapper
{ ... }
}

Does that make sense?

Aug 23 '07 #6
On 23 Aug, 13:15, Paul <paul.tho...@corpoflondon.gov.ukwrote:
Are you essentially looking to have a generic access point in you DAL
for save / load?

If so generics and constraints will work.

Assuming we have an interface ISaveableBusObj
And we have I_TAccessibleWrapper - this interface will define a method
called T getmyObj<T>()

We could have

public class dataLayer
{
public bool saveMyObj<T>(T objToSave) where T : ISaveableObj
{ ... }

public bool saveMyObj<T,W>(W wrapper) where T : ISaveableObj
where W : I_TAccessibleWrapper
{ ... }

}

Does that make sense?
OK, I could look at this though it would seem to be swapping generic
classes with methods, for classes with generic methods - is there much
difference? Anyway, I think I need generic classes because there are
other DAL properties that will differ depending on what kind of object
I am dealing with. So for example I have a property SaveStoredProc
which is different depending on the type of object handler. My
ObjectHandler<Tis abstract and I have a PersonHandler derived from
ObjectHandler<Personand a LocationHandler derived from
ObjectHandler<Location>. Each of these classes has a different
SaveStoredProc. ObjectHandler<T>.saveMyObj basically calls
SaveStoredProc with the correct parameters (simplified version of
events). Also if I switched away form generic classes now it would be
a lot of work I think...!

The object being passed to the saveMyObj is in effect a wrapper class
anyway (AddRequest) because there are other things I need like
DbTransaction etc. But the BusinessObject property of that AddRequest
will either be T or Wrapper<Tso your code would change like this:
public class dataLayer
{
public bool saveMyObj<T>(AddRequest<TaddRqs) where T :
ISaveableObj
{ ... }

public bool saveMyObj<T,W>(AddRequest<WaddRqs) where T :
ISaveableObj
where W : I_TAccessibleWrapper
{ ... }
}

is that right? So if my Business Layer had 2 methods(again the
BusinessManager is object specific much like the DAL so there is a
PersonManager derived from ObjectManager<Person>):

protected internal bool AddObject<T>(T myObj) where T : ISaveableObj
and
protected internal bool AddObject<T,W>(W myObj) where T : ISaveableObj
where W : I_TAccessibleWrapper

and each of these methods did mostly the same thing, i.e
BusinessStuff, SetupRequestObject etc so I put this into a generic
method:
private bool AddObject<E>(E myObj)
{
BusinessStuff();
AddRequest<EaddRqs = new AddRequest<E>();
addRqs.BusinessObject = myObj;
addRqs.DbTransaction = dbTrans;
ISaveableDAL dalHandler = new dalLayer(); //using your suggestion
for standard class with generic methods.
dalHandler.AddObject(addRqs);
}

this would still fail with the same problem wouldn't it? So how do I
organise the Business Layer so that I have a generic method like
AddObject<Eabove that only allows either a T object or a Wrapper<T>
object?

getting very confused now but thanks for suggestions.

Aug 23 '07 #7
Ok, I think you are getting there.

The only thing you can do with generics to try and ensure what you are
getting is to add constraints.

You can also internally do some switching, for example in my code I
make heavy use of empty interface defs.

For example

public interface IAdminAccessRequired
{
}

In my code I may have

public bool saveMyObj<T>( T myBusObj, IUser authorisedUser ) where T :
ISaveable
{
// Check does this data require a User and Auth?
if( myBusObj is IAdminAccessRequired )
{
If( authorisedUser == null || authorisedUser.CanAdmin ==
false )
{
.....
}
}
}

So by using a series of constraints and Interface tests you can wield
a fair amount of code control even in a generic situation.

BUT

really, everything we are dicussing could also be done with some
carefully thought out interfaces

Aug 23 '07 #8
ph*****@googlemail.com wrote:
[...]
Now that I write this more
clearly I start to understand that the compiler does not know that
another object might be sent to this method.
I believe that is true. What I was playing with regarding constraints
was having both T and Wrapper<Tinherit a common interface, so that
they could be treated the same. But in that case, all that the compiler
knows still is that they implement the common interface. That means the
"manager" method would have to be changed to take an object with the
common interface as a parameter, rather than using the overload. That's
possible, but it introduces new complexities itself.

The basic issue here is that with generics, the compiler needs to know
what method is going to be called when it compiles the code. More
problematically, it can't defer that until some concrete use of the
generic. Everything the compiler needs to know must be known when
compiling the generic class itself (consider generic classes implemented
in a pre-compiled assembly, like those already in .NET, for example),
and generics don't provide any way for you to relate T and Wrapper<Tin
a way that makes sense at compile time.

In the error you're getting, the compiler has selected an overload
already -- it has to pick the overload at compile time -- and then it
finds that it doesn't have enough information to consistently ensure
that the parameter passed to the overload is always what it needs. Thus
the error.
What I need is to be able
to tell it that E is either T or Wrapper<Tbut I don't think this is
possible. I suppose I will need to use overloaded methods here but I
was trying to avoid that because all of the code is actually generic
for that method on the assumption you know it is only one of these 2
types that will be sent in :o(

If anyone has any further advice I would appreciate it.
I agree with your assessment that exactly what you want isn't possible.

However, I will say that often when I find that I'm unable to do
something with generics that I'd like to do, if I take a step back and
try to figure out what it is about my underlying design that imposes the
desire to use generics in a specific way, I discover that my underlying
design is leading me down a path that's itself not a desirable one.

In a way, the barricade I run into with respect to the generic
implementation is actually a big warning flag saying that my basic
design could be improved.

Whether this is the case in your situation, I don't know. You would
have to look at a wider picture than what you've shown here, I think.
Just as an example though, do you really need to put your "value-added"
stuff in a generic "Wrapper<>" class? Or does that Wrapper<class need
to be structured in exactly the way it is? I haven't thought about this
much, but if Wrapper<Tactually inherited T, then you could always pass
a Wrapper<Tto any method that took a T. You wouldn't need to use
overloads, but the methods would have to check the object passed in to
see whether it's a Wrapper<Tor just a plain T.

Anyway, that's just an example...if that doesn't actually work, there
are other ways to create a data structure that can be, essentially "T,
or T+other stuff" in a way that is more compatible with generics (that
is, more of the logic happens at run-time, getting around the problem
that at compile time there's not enough information to resolve ambiguities).

Pete
Phil
Aug 23 '07 #9
On 23 Aug, 19:03, Peter Duniho <NpOeStPe...@NnOwSlPiAnMk.comwrote:
phan...@googlemail.com wrote:
[...]
Now that I write this more
clearly I start to understand that the compiler does not know that
another object might be sent to thismethod.

I believe that is true. What I was playing with regarding constraints
was having both T and Wrapper<Tinherit a common interface, so that
they could be treated the same. But in that case, all that the compiler
knows still is that they implement the common interface. That means the
"manager"methodwould have to be changed to take an object with the
common interface as a parameter, rather than using the overload. That's
possible, but it introduces new complexities itself.

The basic issue here is that with generics, the compiler needs to know
whatmethodis going to be called when it compiles the code. More
problematically, it can't defer that until some concrete use of thegeneric. Everything the compiler needs to know must be known when
compiling thegenericclassitself (considergenericclasses implemented
in a pre-compiled assembly, like those already in .NET, for example),
and generics don't provide any way for you to relate T and Wrapper<Tin
a way that makes sense at compile time.

In the error you're getting, the compiler has selected an overload
already -- it has to pick the overload at compile time -- and then it
finds that it doesn't have enough information to consistently ensure
that the parameter passed to the overload is always what it needs. Thus
the error.
What I need is to be able
to tell it that E is either T or Wrapper<Tbut I don't think this is
possible. I suppose I will need to use overloaded methods here but I
was trying to avoid that because all of the code is actuallygeneric
for thatmethodon the assumption you know it is only one of these 2
types that will be sent in :o(
If anyone has any further advice I would appreciate it.

I agree with your assessment that exactly what you want isn't possible.

However, I will say that often when I find that I'm unable to do
something with generics that I'd like to do, if I take a step back and
try to figure out what it is about my underlying design that imposes the
desire to use generics in a specific way, I discover that my underlying
design is leading me down a path that's itself not a desirable one.

In a way, the barricade I run into with respect to thegeneric
implementation is actually a big warning flag saying that my basic
design could be improved.

Whether this is the case in your situation, I don't know. You would
have to look at a wider picture than what you've shown here, I think.
Just as an example though, do you really need to put your "value-added"
stuff in ageneric"Wrapper<>"class? Or does that Wrapper<>classneed
to be structured in exactly the way it is? I haven't thought about this
much, but if Wrapper<Tactually inherited T, then you could always pass
a Wrapper<Tto anymethodthat took a T. You wouldn't need to use
overloads, but the methods would have to check the object passed in to
see whether it's a Wrapper<Tor just a plain T.

Anyway, that's just an example...if that doesn't actually work, there
are other ways to create a data structure that can be, essentially "T,
or T+other stuff" in a way that is more compatible with generics (that
is, more of the logic happens at run-time, getting around the problem
that at compile time there's not enough information to resolve ambiguities).

Pete


Phil
Good stuff to think about. I started thinking about the Wrapper<T>
inheriting from T but how could I do that? I currently have an
interface defined for Wrapper<T>:
T BusinessObject {get; set; }
object AdditionalProperties {get: set: }

(btw, I don't have access to the definitions of T, ie the Business
Objects, so cannot modify them to just have an AdditionalProperties
attribute).
Wrapper<Timplements this interface. If I could derive Wrapper<T>
from T (and I'm fairly sure this is NOT possible is it?), I couldn't
derive the interface because the Business Objects do not implement a
basic interface (i didn't write them).

thanks
Phil

Aug 24 '07 #10
ph*****@googlemail.com wrote:
Good stuff to think about. I started thinking about the Wrapper<T>
inheriting from T but how could I do that? I currently have an
interface defined for Wrapper<T>:
T BusinessObject {get; set; }
object AdditionalProperties {get: set: }

(btw, I don't have access to the definitions of T, ie the Business
Objects, so cannot modify them to just have an AdditionalProperties
attribute).
Wrapper<Timplements this interface. If I could derive Wrapper<T>
from T (and I'm fairly sure this is NOT possible is it?), I couldn't
derive the interface because the Business Objects do not implement a
basic interface (i didn't write them).
That's right, you can't literally inherit T in the declaration. But you
could redesign the code somehow so that that wasn't necessary. It's
hard for me to be specific since I don't know the specifics of your
architecture, and depending on the actual design it could be impossible.

Alternatively, a wrapper class could share the same base class as all
your other wrappable objects, and include within itself a reference to
some wrappable object. That way both kinds of objects could be passed
the same methods, which would then conditionally process the object
depending on whether it's a wrapper type or something else.

Of course, there is always the constraint-based technique mentioned by
both me and Paul. I had experimented a little with this prior to my
first reply, and found it caused more headaches than I thought it was
worth, as well as changed the fundamental design (with my reasoning
being, if you're going to change the fundamental design anyway, do so in
a simpler way than squeezing the design into generics with constraints :) ).

Pete
Aug 24 '07 #11

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

Similar topics

3
by: Jim Newton | last post by:
hi all, i'm relatively new to python. I find it a pretty interesting language but also somewhat limiting compared to lisp. I notice that the language does provide a few lispy type nicities, but...
3
by: SimonH | last post by:
Hi all, I would like to make a generic set of methods that could be called regardless of the database behind the scenes. One of the methods I would like would take a string sql statement and...
2
by: ljlevend | last post by:
I've noticed that in VS.NET 2.0 Beta 1 that none of the methods in System.Collections.Generic.List are overridable. In my app I currently have over 50 strongly typed ArrayLists that inherit from...
3
by: Tigger | last post by:
I have an object which could be compared to a DataTable/List which I am trying to genericify. I've spent about a day so far in refactoring and in the process gone through some hoops and hit some...
0
by: Mikkel Blanné | last post by:
I haven't been able to find any references to using this combination of technologies (remoting + generic methods + method overloading). I don't think the problem has to do with C#, but I couldn't...
9
by: Steve Richter | last post by:
in a generic class, can I code the class so that I can call a static method of the generic class T? In the ConvertFrom method of the generic TypeConvert class I want to write, I have a call to...
13
by: rkausch | last post by:
Hello everyone, I'm writing because I'm frustrated with the implementation of C#'s generics, and need a workaround. I come from a Java background, and am currently writing a portion of an...
26
by: raylopez99 | last post by:
Here is a good example that shows generic delegate types. Read this through and you'll have an excellent understanding of how to use these types. You might say that the combination of the generic...
0
by: =?Utf-8?B?TW9ydGVuIFdlbm5ldmlrIFtDIyBNVlBd?= | last post by:
"Anders Borum" wrote: Hi Anders, I'm afraid the GetMethod() does not currently support filtering on generic parameters so you will have to loop through the existing methods using...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
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,...
0
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...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
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...
0
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...
0
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...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

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.